Skip to content
intermediate Phase 8 · Networking

HTTP Basics

Understand HTTP methods, status codes, headers, and request/response lifecycle on Android.

35m
0 problems
Topic Progress 0%

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

  1. Connection pooling: Reuses connections across requests
  2. Automatic retries: Handles transparent HTTP/1.1 upgrades
  3. Interceptors: Modify requests and responses in a chain
  4. Certificate pinning: Built-in security support
  5. 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?

Question 1 options

2. What does a 429 status code indicate?

Question 2 options

3. Why does Android throw NetworkOnMainThreadException?

Question 3 options

4. What is the benefit of connection pooling in OkHttp?

Question 4 options

Flashcards

Question

What is the difference between PUT and PATCH?

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?

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?

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?

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