HTTP and HTTPS are the protocols that power the web. Understanding how they work is essential for deploying web services, debugging connectivity issues, and building scalable APIs.
HTTP Basics
HTTP (HyperText Transfer Protocol) is a request-response protocol for transferring data:
Client Server
↓ (Request: GET /index.html) ↓
├─────────────────────────────→
│
← (Response: 200 OK) ←
├─────────────────────────────┤
│ [HTML content] │
│
Key Characteristics:
- Stateless — Each request independent
- Request-Response — Client initiates, server responds
- Plain text — Human-readable headers
- Port 80 — Default for HTTP
- Insecure — No encryption (visible to anyone on network)
HTTP Versions
| Version | Release | Speed | Multiplexing | Server Push | Status |
|---|---|---|---|---|---|
| HTTP/1.0 | 1996 | Slow | No | No | Obsolete |
| HTTP/1.1 | 1997 | Moderate | No | No | Still used |
| HTTP/2 | 2015 | Fast | Yes | Yes | Common |
| HTTP/3 | 2022 | Faster | Yes | Yes | Modern |
HTTP/1.1 Problem: Each request needs separate TCP connection
Request 1 → Connection 1 → Response 1
Request 2 → Connection 2 → Response 2
Request 3 → Connection 3 → Response 3
→ Slow! Multiple connections = overhead
HTTP/2 Solution: Multiplexing over single connection
Request 1 ─┬→ Single Connection → Response 1
Request 2 ─┤ → Response 2
Request 3 ─┘ → Response 3
→ Fast! All requests over same connection
HTTP Request
Anatomy of an HTTP request:
GET /api/users HTTP/1.1
Host: api.example.com
User-Agent: curl/7.68.0
Accept: application/json
Authorization: Bearer token123
Content-Length: 0
[Optional body for POST/PUT/PATCH]
Components:
- Method (GET, POST, PUT, DELETE, PATCH)
- Path (/api/users)
- Version (HTTP/1.1)
- Headers (Host, User-Agent, Authorization)
- Body (data payload for POST/PUT)
HTTP Methods
| Method | Purpose | Safe | Idempotent | Body |
|---|---|---|---|---|
| GET | Retrieve data | Yes | Yes | No |
| POST | Create new resource | No | No | Yes |
| PUT | Replace entire resource | No | Yes | Yes |
| PATCH | Partial update | No | No | Yes |
| DELETE | Remove resource | No | Yes | No |
| HEAD | Like GET, no body | Yes | Yes | No |
| OPTIONS | Query allowed methods | Yes | Yes | No |
Safe: Doesn't modify data on server Idempotent: Multiple calls = same result
HTTP Status Codes
| Code | Category | Meaning | Examples |
|---|---|---|---|
| 1xx | Informational | Request received, continuing | 100 Continue |
| 2xx | Success | Request succeeded | 200 OK, 201 Created |
| 3xx | Redirect | Further action needed | 301 Moved, 304 Not Modified |
| 4xx | Client Error | Bad request | 400 Bad Request, 404 Not Found |
| 5xx | Server Error | Server failed | 500 Server Error, 503 Unavailable |
Common Codes:
200 OK Request succeeded
201 Created Resource created successfully
204 No Content Success, no response body
301 Moved Permanently Redirect to new location
304 Not Modified Use cached version
400 Bad Request Invalid syntax
401 Unauthorized Authentication required
403 Forbidden Permission denied
404 Not Found Resource doesn't exist
500 Server Error Unexpected error
503 Service Unavailable Server temporarily down
HTTPS (HTTP Secure)
HTTPS is HTTP over TLS/SSL encryption:
HTTP: Client ←→ Server (plain text, visible)
HTTPS: Client ←TLS/SSL→ Server (encrypted, invisible)
Differences:
- Port 443 (vs HTTP port 80)
- TLS handshake before data transfer
- Certificates verify server identity
- Encryption protects data
- Required for sensitive data (login, payment)
HTTPS Connection Establishment
Client Server
├─ ClientHello (supported ciphers) ──→
├──────────────────────────────────→ ServerHello
├← ServerCertificate (public key) ←──┤
├← ServerKeyExchange
├← ServerHelloDone
├─ ClientKeyExchange (symmetric key)→
├─ ChangeCipherSpec ─────────────────→
├─ Finished (encrypted) ────────────→
├← ChangeCipherSpec
├← Finished (encrypted)
│
└─ Encrypted data transfer ←────────→
(Now all data is encrypted)
HTTP Headers
Request Headers (client → server):
Host: api.example.com # Server hostname
Authorization: Bearer token123 # Authentication
Content-Type: application/json # Request body format
Accept: application/json # Desired response format
User-Agent: curl/7.68.0 # Client identifier
Cache-Control: no-cache # Caching instructions
If-Modified-Since: <date> # Conditional request
Cookie: session_id=abc123 # Session data
Response Headers (server → client):
Content-Type: application/json # Response body format
Content-Length: 1024 # Body size in bytes
Cache-Control: max-age=3600 # Cache for 1 hour
Set-Cookie: session_id=xyz789; Path=/ # Set session cookie
Location: /api/users/123 # Redirect target
ETag: "abc123" # Version identifier
Access-Control-Allow-Origin: * # CORS (cross-origin)
Strict-Transport-Security: max-age=31536000 # Force HTTPS
REST API Example
Making HTTP requests:
# GET request
curl -X GET "http://api.example.com/users" \
-H "Authorization: Bearer token123" \
-H "Accept: application/json"
# POST request (create)
curl -X POST "http://api.example.com/users" \
-H "Content-Type: application/json" \
-d '{"name": "Alice", "email": "alice@example.com"}'
# PUT request (replace)
curl -X PUT "http://api.example.com/users/123" \
-H "Content-Type: application/json" \
-d '{"name": "Bob", "email": "bob@example.com"}'
# DELETE request
curl -X DELETE "http://api.example.com/users/123"HTTP Connection Management
Keep-Alive (persistent connections):
# HTTP/1.1 keeps connection open by default
curl -v http://example.com
# Output: Connection #0 to example.com left intact
# (Connection stays open for next request)Connection Pooling:
Application
↓
Pool 1: ← Connection to api.example.com
Pool 2: ← Connection to db.example.com
Pool 3: ← Connection to cache.example.com
↓
Reuse connections instead of creating new ones
Checking HTTP/HTTPS
View response headers:
curl -i http://example.com
# Output:
# HTTP/1.1 200 OK
# Date: Wed, 09 Apr 2026 10:00:00 GMT
# Server: nginx/1.18.0
# Content-Length: 1234
# Content-Type: text/htmlCheck HTTP version:
curl -w "HTTP Version: %{http_version}\n" http://example.com
# Result: HTTP Version: 1.1 or 2.0Test HTTPS certificate:
openssl s_client -connect example.com:443
# Shows certificate details, chain, expirationHTTP/HTTPS Best Practices
1. Always Use HTTPS
✓ Encrypt all traffic
✓ Verify server identity
✗ Never use HTTP for sensitive data
2. Set Appropriate Cache Headers
# Cache static assets
Cache-Control: public, max-age=31536000
# Don't cache sensitive data
Cache-Control: no-store, no-cache3. Use Connection Pooling
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retry = Retry(connect=3, backoff_factor=0.5)
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
# Now session reuses connections
response = session.get('http://api.example.com/users')4. Implement Compression
Accept-Encoding: gzip, deflate
# Server responds with:
Content-Encoding: gzip
# Saves bandwidth on large responses
5. Monitor Performance
# Measure response time
time curl http://example.com
# Check connection time vs response time
curl -w "Connect: %{time_connect}\nTotal: %{time_total}\n" http://example.comKey Concepts
- HTTP = Request-response protocol for web
- HTTPS = HTTP over TLS/SSL encryption
- Methods = GET, POST, PUT, DELETE, PATCH
- Status Codes = 2xx (success), 3xx (redirect), 4xx (client error), 5xx (server error)
- Headers = Metadata about request/response
- Port 80 = HTTP, Port 443 = HTTPS
- Stateless = Each request independent
- Keep-Alive = Reuse TCP connections
- Always use HTTPS for production
- Use appropriate cache headers for performance