Basics of HTTP
0) What HTTP is (and isn’t)
- HTTP = text-based request/response protocol on top of TCP (or QUIC for HTTP/3).
- Stateless: each request stands alone (servers remember you via cookies/tokens).
- Ports: 80 (HTTP), 443 (HTTPS over TLS).
1) The URL
https://api.example.com:443/users?id=42#section
└scheme┘ └── host ───┘ :port └ path ┘ └query┘ └fragment (client-only)2) An HTTP request (anatomy)
<Request line> -> METHOD SP PATH SP VERSION
<Headers> -> key: value
(blank line)
<Body> (optional)Raw GET (HTTP/1.1)
GET / HTTP/1.1
Host: example.com
User-Agent: curl/8.0
Accept: */*
Connection: closeTry it:
# Plain HTTP
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' | nc example.com 80# HTTPS (uses TLS)
printf 'GET / HTTP/1.1\r\nHost: example.com\r\nConnection: close\r\n\r\n' | openssl s_client -quiet -connect example.com:443 -servername example.com3) An HTTP response (anatomy)
<Status line> -> VERSION SP STATUS-CODE SP REASON
<Headers>
(blank line)
<Body> (optional)Example:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1256
Cache-Control: max-age=3600<html>...</html>4) Methods (what you’re asking the server to do)
- GET (safe, idempotent): fetch a resource.
- HEAD: like GET, but no body (metadata only).
- POST: create / process (non-idempotent).
- PUT (idempotent): replace a resource.
- PATCH: partial update.
- DELETE (idempotent): remove.
- OPTIONS: capabilities/preflight.
- TRACE, CONNECT: special/rare.
Idempotent = repeating the request has the same effect.
5) Headers you’ll use a lot
- Host, User-Agent, Accept, Accept-Encoding, Accept-Language
- Content-Type, Content-Length (or Transfer-Encoding: chunked)
- Authorization (e.g.,
Bearer <token>) - Cookie / Set-Cookie
- Cache-Control, ETag, If-None-Match, Last-Modified
- Location (redirects)
- Range / Content-Range
- Access-Control-* (CORS)
6) Sending data (four common ways)
a) Query string (GET)
GET /search?q=android&page=2 HTTP/1.1curl "https://httpbin.org/get?q=android&page=2"b) Form fields (URL-encoded)
Content-Type: application/x-www-form-urlencodedname=Prashant&role=devcurl -X POST https://httpbin.org/post \
-H "Content-Type: application/x-www-form-urlencoded" \
--data "name=Prashant&role=dev"c) JSON
Content-Type: application/json{"name":"Prashant","role":"dev"}curl -X POST https://httpbin.org/post \
-H "Content-Type: application/json" \
-d '{"name":"Prashant","role":"dev"}'d) File upload (multipart/form-data)
Content-Type: multipart/form-data; boundary=----abccurl -X POST https://httpbin.org/post \
-F "avatar=@photo.jpg" \
-F "note=hello"7) Receiving data (how bodies arrive)
- Known length:
Content-Length: N. - Streaming:
Transfer-Encoding: chunked(arrives in pieces). - Compressed:
Content-Encoding: gzip(client should sendAccept-Encoding: gzip, br).
Resuming big downloads:
curl -C - -O https://speed.hetzner.de/100MB.bin # uses Range under the hood8) Status codes (what happened)
- 2xx success: 200 OK, 201 Created, 204 No Content
- 3xx redirect: 301/308 (permanent), 302/307 (temporary)
- 4xx client error: 400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests
- 5xx server error: 500, 502, 503, 504
Get Prashant Mondkar’s stories in your inbox
Join Medium for free to get updates from this writer.
Follow redirects:
curl -L http://example.com9) Caching & conditional requests (save bandwidth)
- Server hints:
Cache-Control: max-age=600, public,ETag: "abc123",Last-Modified: Wed, 14 Aug 2024 12:00:00 GMT - Client revalidation:
# First fetch
curl -i https://httpbin.org/etag/abc123# Revalidate with If-None-Match
curl -i https://httpbin.org/etag/abc123 -H 'If-None-Match: "abc123"' # expect 304 Not Modified10) Cookies & sessions
Server sets:
Set-Cookie: sid=xyz; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=3600Client sends back:
Cookie: sid=xyz11) Auth (common patterns)
- Basic:
Authorization: Basic base64(user:pass)(only over HTTPS). - Bearer (e.g., JWT/OAuth access token):
Authorization: Bearer <token>. - API keys: header or query (header is better).
- OAuth 2.0 / OIDC: browser-based token dance.
12) HTTPS (TLS)
- Encrypts & authenticates the connection (certificates).
- Modern servers use HSTS to force HTTPS.
- SNI/ALPN negotiate host & protocol (e.g., HTTP/2).
13) HTTP/1.1 vs HTTP/2 vs HTTP/3 (big picture)
- HTTP/1.1: text, one request per connection (keep-alive pipelines have head-of-line blocking).
- HTTP/2: binary frames, multiplexing, HPACK header compression (much faster).
- HTTP/3: runs over QUIC (UDP), better latency and loss recovery, QPACK header compression.
You still write the same requests; the wire format differs.
14) CORS (browser-only rule)
- Cross-origin requests may require:
- Response:
Access-Control-Allow-Origin: https://your.app - Preflight (browser sends
OPTIONSwithAccess-Control-Request-*) - Not relevant to native apps/servers — only browsers enforce it.
15) Content negotiation
Client says what it can accept:
Accept: application/json
Accept-Language: en-IN
Accept-Encoding: gzip, brServer chooses accordingly (and may send Vary headers).
16) Upgrades & streaming
- Server-Sent Events (SSE): one-way event stream (
text/event-stream). - WebSockets:
Upgrade: websocketto switch protocols for full-duplex. - HTTP/1.1 chunked: stream chunks as you generate them.
17) Proxies & CDNs
- Forward proxy: client → proxy → internet.
- Reverse proxy (nginx, HAProxy, Cloudflare): internet → proxy → your app.
- Common for TLS termination, caching, load balancing, rate limits.
Mini “cheat” lab (copy-paste ready)
Inspect a response
curl -i https://httpbin.org/getSend JSON
curl -i https://httpbin.org/post \
-H "Content-Type: application/json" \
-d '{"hello":"world"}'Upload a file
curl -i -F "file=@/path/to/file.zip" https://httpbin.org/postConditional GET
curl -i https://httpbin.org/cache/60 # check Cache-Control/DateQuick client code (Android/Java with OkHttp)
// build.gradle: implementation("com.squareup.okhttp3:okhttp:4.12.0")
OkHttpClient client = new OkHttpClient();// GET
Request get = new Request.Builder()
.url(https://medium.com/"https://httpbin.org/get?q=android")
.build();
try (Response resp = client.newCall(get).execute()) {
System.out.println(resp.code());
System.out.println(resp.header("Content-Type"));
System.out.println(resp.body().string());
}// POST JSON
MediaType JSON = MediaType.get("application/json; charset=utf-8");
RequestBody body = RequestBody.create("{\"name\":\"Prashant\"}", JSON);
Request postJson = new Request.Builder()
.url(https://medium.com/"https://httpbin.org/post")
.post(body)
.build();// Multipart upload
File file = new File("/path/to/photo.jpg");
RequestBody filePart = RequestBody.create(file, MediaType.parse("image/jpeg"));
RequestBody multipart = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("avatar", file.getName(), filePart)
.addFormDataPart("note", "hello")
.build();
Request upload = new Request.Builder()
.url(https://medium.com/"https://httpbin.org/post")
.post(multipart)
.build();
Mental model recap
- Client sends method + path + headers + optional body.
- Server replies with status + headers + optional body.
- Everything else (auth, caching, cookies, CORS, compression, streaming) is just rules around those two lines.





