HTTP Methods and Status Codes
HTTP Methods
HTTP defines several request methods, each with a specific purpose:
| Method | Purpose | Request Body | Safe | Idempotent |
|---|---|---|---|---|
| GET | Retrieve data | No | Yes | Yes |
| POST | Create resource | Yes | No | No |
| PUT | Replace resource | Yes | No | Yes |
| PATCH | Partial update | Yes | No | No |
| DELETE | Remove resource | Optional | No | Yes |
Safe methods do not modify server state. Idempotent methods produce the same result when called multiple times.
Status Code Categories
Status codes fall into five classes:
- 1xx Informational: Request received, processing continues
- 2xx Success: Request accepted and processed (200 OK, 201 Created, 204 No Content)
- 3xx Redirection: Further action needed (301 Moved, 304 Not Modified)
- 4xx Client Error: Bad request from client (400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests)
- 5xx Server Error: Server failed to fulfill request (500 Internal, 503 Unavailable)
// Handling status codes in Android
val response = client.newCall(request).execute()
when (response.code) {
in 200..299 -> handleSuccess(response)
401 -> redirectToLogin()
404 -> showNotFound()
429 -> retryWithBackoff(response.header("Retry-After"))
in 500..599 -> showServerError()
}
The 429 status code is critical for mobile apps — Android has strict retry budgets. Always respect Retry-After and RateLimit-* headers.
Request and Response Structure
HTTP Request Anatomy
An HTTP request has three parts: a start line, headers, and a body.
POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOi...
Accept-Language: en-US
{"name": "Alice", "email": "alice@example.com"}
Start line: method + path + version. Headers: metadata about the request. Body: the payload (only for POST/PUT/PATCH).
HTTP Response Anatomy
HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: max-age=3600
ETag: "abc123"
{"id": 42, "name": "Alice", "email": "alice@example.com"}
The response has its own status line, headers, and body.
Headers That Matter on Android
| Header | Purpose | Android Impact |
|---|---|---|
Content-Type |
Body format | Determines deserialization |
Authorization |
Auth token | Include in every protected request |
Cache-Control |
Caching rules | OkHttp honors these automatically |
Connection: keep-alive |
Connection reuse | Improves latency on repeated calls |
Accept-Encoding: gzip |
Compression | Reduces data usage |
Connection Behavior on Android
Android's default HttpURLConnection and OkHttp both use connection pooling. When you call the same host repeatedly, the underlying TCP connection is reused. This avoids the TLS handshake overhead, which costs 1-2 round trips on first connection.
// Connection pooling is handled by OkHttp automatically
val client = OkHttpClient.Builder()
.connectionPool(
ConnectionPool(
maxIdleConnections = 5,
keepAliveDuration = 5,
timeUnit = TimeUnit.MINUTES
)
)
.build()
Keep-alive connections on mobile are especially valuable because every handshake burns battery and adds latency.
HTTP in Android Practice
HttpURLConnection (Legacy)
Android still ships with HttpURLConnection. It works but is verbose and error-prone:
fun fetchUser(id: Int): User? {
val url = URL("https://api.example.com/users/$id")
val connection = url.openConnection() as HttpURLConnection
return try {
connection.connectTimeout = 15_000
connection.readTimeout = 15_000
connection.setRequestProperty("Accept", "application/json")
if (connection.responseCode == 200) {
val json = connection.inputStream.bufferedReader().readText()
Gson().fromJson(json, User::class.java)
} else {
null
}
} finally {
connection.disconnect()
}
}
This approach lacks interceptors, automatic retries, and caching control. Modern Android code uses OkHttp or Retrofit instead.
Why OkHttp Wins on Android
- Connection pooling: Reuses connections across requests
- Automatic retries: Handles transparent HTTP/1.1 upgrades
- Interceptors: Modify requests and responses in a chain
- Certificate pinning: Built-in security support
- Gzip support: Transparent compression
Common Pitfalls
Forgetting to close streams: Always use response.use {} or try/finally to close response bodies. Leaking a response body holds the connection open.
Blocking the main thread: Never call response.body?.string() on the main thread. Android throws NetworkOnMainThreadException.
Ignoring content encoding: If the server sends gzip-compressed data, you must read it through the correct stream or decode it manually.
// Correct pattern: coroutine + response.use
viewModelScope.launch {
withContext(Dispatchers.IO) {
val response = client.newCall(request).execute()
response.use {
if (it.isSuccessful) {
val body = it.body?.string() ?: return@use
val user = gson.fromJson(body, User::class.java)
_userState.value = user
}
}
}
}
Quiz
1. Which HTTP method is idempotent and safe?
2. What does a 429 status code indicate?
3. Why does Android throw NetworkOnMainThreadException?
4. What is the benefit of connection pooling in OkHttp?
Flashcards
Question
What is the difference between PUT and PATCH?
Click to reveal answer
Answer
PUT replaces the entire resource with a new representation. PATCH applies a partial update, modifying only specified fields.
Question
What does 304 Not Modified mean?
Click to reveal answer
Answer
The server indicates the client's cached version is still valid. No body is returned. The client can use its local copy, saving bandwidth.
Question
Why must response bodies be closed on Android?
Click to reveal answer
Answer
Unclosed response bodies hold the underlying TCP connection open, preventing it from returning to the connection pool. This leads to connection exhaustion and memory leaks.
Question
What is the purpose of the Accept-Encoding header?
Click to reveal answer
Answer
Tells the server which compression algorithms the client supports (e.g., gzip, br). OkHttp adds this automatically, and transparently decompresses the response.
Revision Notes
Key Takeaways
- 1. GET, PUT, DELETE are idempotent; POST and PATCH are not
- 2. Always handle 429 with Retry-After backoff on mobile
- 3. Close response bodies to prevent connection exhaustion
- 4. OkHttp handles connection pooling, retries, and gzip transparently
Interview Tips
- • Explain the difference between idempotent and safe methods
- • Discuss why Android blocks network calls on the main thread
- • Describe the tradeoff between connection pooling and memory usage
- • Know common status codes and what they mean for client behavior
Cheat Sheet
HTTP Basics Cheat Sheet
Methods:
- GET: Read (safe, idempotent)
- POST: Create (not idempotent)
- PUT: Replace (idempotent)
- PATCH: Partial update
- DELETE: Remove (idempotent)
Status Codes:
- 200 OK / 201 Created / 204 No Content
- 301 Moved Permanently / 304 Not Modified
- 400 Bad Request / 401 Unauthorized / 403 Forbidden / 404 Not Found / 429 Rate Limited
- 500 Server Error / 503 Unavailable
Key Headers:
- Content-Type, Authorization, Cache-Control, Accept-Encoding, ETag
Android Rules:
- Never call OkHttp on main thread
- Always close response bodies (use response.use {})
- OkHttp handles connection pooling and gzip automatically