What is HTTP?
HTTP (HyperText Transfer Protocol) is the foundation of the World Wide Web and the protocol that makes the internet work as we know it. Every time you visit a website, check your email through a web browser, stream a video, or use a mobile app that connects to the internet, HTTP is working behind the scenes.
HTTP defines how messages are formatted and transmitted, and what actions web servers and browsers should take in response to various commands. It's the "language" that clients (like your browser) and servers speak to each other.
A Simple Analogy: The Postal System
Understanding HTTP becomes easier when you compare it to sending letters:
- HTTP Request = Sending a Letter: You write a letter (the body), put it in an envelope with an address (the URL), specify what kind of response you want (headers like "Accept"), and indicate the purpose (GET to request information, POST to submit something).
- HTTP Response = Receiving a Reply: The recipient processes your request and sends back a response. The response includes a status (success, failure, not found), metadata about the content, and the actual content itself.
- Protocol = Postal Rules: Everyone follows the same rules—envelopes have addresses in specific places, stamps go in the corner, ZIP codes help with routing. HTTP has similar standardized rules that all web software follows.
HTTP (HyperText Transfer Protocol) is the application-layer protocol for transmitting hypermedia documents (like HTML). Its key characteristics:
- Request-Response Model: Communication is always initiated by the client. The server waits for requests and sends responses.
- Stateless: Each request is completely independent. The server doesn't remember previous requests (though we can add state with sessions and cookies).
- Text-based (HTTP/1.x): Requests and responses are human-readable plain text, making debugging easier.
- Extensible: Headers can carry custom metadata, allowing protocols to be built on top of HTTP.
- Port 80 (HTTP) / Port 443 (HTTPS): These are the default ports, though any port can be used.
A Brief History of HTTP
Understanding HTTP's evolution helps explain why things work the way they do today:
- HTTP/0.9 (1991): The original version. Only GET method, only HTML responses, no headers. Tim Berners-Lee created it at CERN.
- HTTP/1.0 (1996): Added headers, status codes, POST method, content types. Each request required a new TCP connection.
- HTTP/1.1 (1997): Added persistent connections (keep-alive), chunked transfers, caching improvements, the Host header. Still the most commonly used version.
- HTTP/2 (2015): Binary protocol (not text), multiplexing (multiple requests over one connection), server push, header compression. Major performance improvement.
- HTTP/3 (2022): Uses QUIC instead of TCP, even faster connection establishment, better handling of packet loss. Gradually being adopted.
As a Java developer, you'll primarily work with HTTP/1.1 concepts, but the principles apply across versions.
// HTTP communication flow
Client Server
│ │
│ ─────── HTTP Request ──────────▶ │
│ GET /api/users HTTP/1.1 │
│ Host: api.example.com │
│ │
│ ◀────── HTTP Response ───────── │
│ HTTP/1.1 200 OK │
│ Content-Type: application/json │
│ {"users": [...]} │
│ │
HTTP Request Structure
// Complete HTTP Request breakdown
┌─────────────────────────────────────────────────────────────┐
│ REQUEST LINE │
│ GET /api/products/123?include=reviews HTTP/1.1 │
│ ─── ─────────────────────────────────── ──────── │
│ │ │ │ │
│ Method Path + Query Version │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ HEADERS │
│ Host: api.example.com │
│ Accept: application/json │
│ Authorization: Bearer eyJhbGciOiJIUzI1NiIs... │
│ Content-Type: application/json │
│ User-Agent: Mozilla/5.0 │
└─────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ BODY (optional, for POST/PUT/PATCH) │
│ { │
│ "name": "New Product", │
│ "price": 29.99 │
│ } │
└─────────────────────────────────────────────────────────────┘
Reading Request in Java (Spring)
@PostMapping("/api/products")
public Product createProduct(
// Request body - automatically parsed from JSON
@RequestBody Product product,
// Path variable - from URL
@PathVariable("id") Long id,
// Query parameter - ?category=electronics
@RequestParam("category") String category,
// Header value
@RequestHeader("Authorization") String authHeader,
// Full request access
HttpServletRequest request
) {
// Access any part of the request
String method = request.getMethod(); // "POST"
String uri = request.getRequestURI(); // "/api/products"
String query = request.getQueryString(); // "category=electronics"
return productService.create(product);
}
HTTP Methods (Verbs)
| Method | Purpose | Has Body | Idempotent | Safe |
|---|---|---|---|---|
| GET | Retrieve data | No | Yes | Yes |
| POST | Create resource | Yes | No | No |
| PUT | Replace resource | Yes | Yes | No |
| PATCH | Partial update | Yes | No* | No |
| DELETE | Remove resource | No | Yes | No |
| HEAD | GET without body | No | Yes | Yes |
| OPTIONS | Get allowed methods | No | Yes | Yes |
- Idempotent: Same request multiple times = same result
- Safe: Doesn't modify data (read-only)
GET - Retrieve Data
// GET requests retrieve data - never modify anything!
// Request
GET /api/users/123 HTTP/1.1
Host: api.example.com
Accept: application/json
// Java handler
@GetMapping("/api/users/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
// GET with query parameters
GET /api/users?page=1&size=10&sort=name HTTP/1.1
@GetMapping("/api/users")
public Page<User> getUsers(
@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size,
@RequestParam(defaultValue = "id") String sort
) {
return userService.findAll(PageRequest.of(page, size, Sort.by(sort)));
}
POST - Create Resource
// POST creates new resources
// Request
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
{
"name": "John Doe",
"email": "john@example.com"
}
// Java handler
@PostMapping("/api/users")
public ResponseEntity<User> createUser(@RequestBody User user) {
User created = userService.create(user);
URI location = URI.create("/api/users/" + created.getId());
return ResponseEntity
.created(location) // 201 Created
.body(created);
}
PUT - Replace Resource
// PUT replaces entire resource (send all fields)
// Request
PUT /api/users/123 HTTP/1.1
Content-Type: application/json
{
"name": "John Updated",
"email": "john.new@example.com",
"phone": "555-1234"
}
// Java handler
@PutMapping("/api/users/{id}")
public User replaceUser(
@PathVariable Long id,
@RequestBody User user
) {
// Replace ALL fields
return userService.replace(id, user);
}
PATCH - Partial Update
// PATCH updates only specified fields
// Request - only updating email
PATCH /api/users/123 HTTP/1.1
Content-Type: application/json
{
"email": "new.email@example.com"
}
// Java handler
@PatchMapping("/api/users/{id}")
public User updateUser(
@PathVariable Long id,
@RequestBody Map<String, Object> updates
) {
// Update only provided fields
return userService.partialUpdate(id, updates);
}
DELETE - Remove Resource
// DELETE removes resources
// Request
DELETE /api/users/123 HTTP/1.1
Host: api.example.com
// Java handler
@DeleteMapping("/api/users/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build(); // 204 No Content
}
HTTP Status Codes
1xx - Informational
// Rarely used directly
100 Continue // Server received headers, send body
101 Switching Protocols// Upgrading to WebSocket
2xx - Success
// Request succeeded
200 OK // Standard success (GET, PUT, PATCH)
201 Created // Resource created (POST)
204 No Content // Success, no body (DELETE)
202 Accepted // Processing started (async operations)
// Java examples
return ResponseEntity.ok(user); // 200
return ResponseEntity.created(location).body(user); // 201
return ResponseEntity.noContent().build(); // 204
return ResponseEntity.accepted().build(); // 202
3xx - Redirection
// Resource moved
301 Moved Permanently // URL changed forever
302 Found // Temporary redirect
304 Not Modified // Use cached version
307 Temporary Redirect // Redirect, keep method
308 Permanent Redirect // Permanent, keep method
// Java redirect
return ResponseEntity
.status(HttpStatus.MOVED_PERMANENTLY)
.location(URI.create("/new-url"))
.build();
4xx - Client Errors
// Client did something wrong
400 Bad Request // Invalid syntax, validation error
401 Unauthorized // Not authenticated (login required)
403 Forbidden // Authenticated but not allowed
404 Not Found // Resource doesn't exist
405 Method Not Allowed // GET when only POST allowed
409 Conflict // Conflict with current state
422 Unprocessable // Valid syntax but invalid data
429 Too Many Requests // Rate limited
// Java exception handling
@ExceptionHandler(NotFoundException.class)
public ResponseEntity<?> handleNotFound(NotFoundException e) {
return ResponseEntity.notFound().build(); // 404
}
@ExceptionHandler(ValidationException.class)
public ResponseEntity<?> handleValidation(ValidationException e) {
return ResponseEntity.badRequest().body(e.getMessage()); // 400
}
5xx - Server Errors
// Server did something wrong
500 Internal Server Error // Generic server error
501 Not Implemented // Feature not supported
502 Bad Gateway // Upstream server error
503 Service Unavailable // Server overloaded/maintenance
504 Gateway Timeout // Upstream server timeout
// Java - let Spring handle 500s for unhandled exceptions
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleGeneric(Exception e) {
log.error("Unexpected error", e);
return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("An unexpected error occurred");
}
Common HTTP Headers
Request Headers
// Headers the client sends
Accept: application/json // I want JSON response
Accept-Language: en-US // Preferred language
Authorization: Bearer eyJ... // Authentication token
Content-Type: application/json // Body format I'm sending
Cookie: sessionId=abc123 // Send cookies
User-Agent: Mozilla/5.0... // Browser/client info
Origin: https://example.com // Where request came from
Cache-Control: no-cache // Caching preferences
Response Headers
// Headers the server sends
Content-Type: application/json // Response body format
Content-Length: 1234 // Body size in bytes
Set-Cookie: sessionId=abc123 // Store this cookie
Location: /api/users/456 // Redirect URL (201, 3xx)
Cache-Control: max-age=3600 // Cache for 1 hour
Access-Control-Allow-Origin: * // CORS header
WWW-Authenticate: Bearer // Auth method (401)
// Setting headers in Java
@GetMapping("/api/report")
public ResponseEntity<byte[]> downloadReport() {
byte[] pdf = reportService.generatePdf();
return ResponseEntity.ok()
.header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=report.pdf")
.contentType(MediaType.APPLICATION_PDF)
.contentLength(pdf.length)
.body(pdf);
}
HTTP vs HTTPS
| Aspect | HTTP | HTTPS |
|---|---|---|
| Port | 80 | 443 |
| Encryption | None (plaintext) | TLS/SSL encrypted |
| Security | Can be intercepted | Secure communication |
| Certificate | Not required | Required |
| Use case | Development only | Production (always!) |
// Spring Boot HTTPS configuration
// application.properties
server.port=8443
server.ssl.enabled=true
server.ssl.key-store=classpath:keystore.p12
server.ssl.key-store-password=changeit
server.ssl.key-store-type=PKCS12
// Redirect HTTP to HTTPS
@Configuration
public class HttpsRedirectConfig {
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(httpConnector());
return tomcat;
}
}
HTTP/1.1 vs HTTP/2 vs HTTP/3
| Feature | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|
| Connections | One request per connection | Multiplexed | Multiplexed |
| Format | Text | Binary | Binary |
| Transport | TCP | TCP | QUIC (UDP) |
| Header compression | No | HPACK | QPACK |
| Server push | No | Yes | Yes |
// Most Java servers support HTTP/2 automatically
// Spring Boot with HTTP/2
// application.properties
server.http2.enabled=true
// Note: HTTP/2 typically requires HTTPS
Testing HTTP with Tools
# curl - Command line HTTP client
# GET request
curl https://api.example.com/users
# GET with headers
curl -H "Authorization: Bearer token123" \
-H "Accept: application/json" \
https://api.example.com/users
# POST with JSON body
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name": "John", "email": "john@example.com"}' \
https://api.example.com/users
# See response headers
curl -i https://api.example.com/users
# Verbose mode (debug)
curl -v https://api.example.com/users
# PUT request
curl -X PUT \
-H "Content-Type: application/json" \
-d '{"name": "John Updated"}' \
https://api.example.com/users/123
# DELETE request
curl -X DELETE https://api.example.com/users/123
Summary
- HTTP: Protocol for client-server communication
- Methods: GET (read), POST (create), PUT (replace), PATCH (update), DELETE (remove)
- Status codes: 2xx success, 4xx client error, 5xx server error
- Headers: Metadata about the request/response
- HTTPS: Always use in production (encrypted)
- Stateless: Each request is independent