入门
HTTP 请求与响应
HTTP 是请求-响应协议。客户端发送请求(方法、路径、头、可选的请求体),服务器以状态、头和响应体回应。HTTP/1.1 基于文本,HTTP/2 和 HTTP/3 使用二进制分帧。
# HTTP Request
GET /api/users HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0
Accept: application/json
# HTTP Response
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 45
{"id": 1, "name": "Alice", "email": "[email protected]"}URL 结构
URL 标识资源。scheme 选择协议。host 通过 DNS 解析。省略时使用默认端口。fragment(#) 仅在客户端使用,在发送到服务器之前会被剥离。查询字符串通常用于过滤/分页。
# Generic URL format
scheme://userinfo@host:port/path?query#fragment
# Example
https://user:[email protected]:8443/api/v1/users?page=2#section
# Components
# scheme - https (protocol)
# userinfo - user:pass (rare, deprecated)
# host - example.com (domain or IP)
# port - 8443 (default: 80 for http, 443 for https)
# path - /api/v1/users (resource location)
# query - page=2 (key=value pairs, & separated)
# fragment - section (client-only, never sent to server)HTTP 版本概览
HTTP/0.9 是一个最小的原型。HTTP/1.0 增加了头和内容类型,但每个请求都打开一个新连接。HTTP/1.1 引入了持久连接、必需的 Host 头(启用虚拟主机)和管道化。HTTP/2 增加了二进制多路复用。HTTP/3 运行在 QUIC 之上,消除了传输层的队头阻塞。
# HTTP/0.9 (1991) - single GET, no headers
GET /page.html
# HTTP/1.0 (1996) - headers, status codes, multiple types
GET /page.html HTTP/1.0
# HTTP/1.1 (1997) - persistent connections, Host header, pipelining
GET /page.html HTTP/1.1
Host: example.com
# HTTP/2 (2015) - binary, multiplexing, header compression
# (negotiated via ALPN or h2c upgrade)
# HTTP/3 (2022) - over QUIC (UDP-based)
# (negotiated via Alt-Svc header)连接生命周期
HTTP/1.1 默认保持 TCP 连接打开(keep-alive),避免了重复握手的开销。多个请求可以通过一个连接发送。Connection: close 头标志最后一个请求。HTTP/2 在单个连接上多路复用多个流。Keep-Alive 超时和最大值可在服务器上配置。
# HTTP/1.1 persistent connection (keep-alive)
GET /page1 HTTP/1.1
Host: example.com
Connection: keep-alive
# (server responds, connection stays open)
HTTP/1.1 200 OK
Content-Length: 128
Connection: keep-alive
# Client reuses same TCP connection for next request
GET /page2 HTTP/1.1
Host: example.com
# Closing the connection
GET /final HTTP/1.1
Host: example.com
Connection: close消息格式
HTTP 消息以起始行(请求行或状态行)开 始,后跟头、空行和可选的请求体。行使用 CRLF 行尾。头名称不区分大小写。空行是必需的,标志请求体的开始。请求体可以是任意长度(分块)或固定长度(Content-Length)。
# Request format
<METHOD> <PATH> <VERSION>
<Header-Name>: <value>
...
<optional body>
# Response format
<VERSION> <STATUS> <REASON>
<Header-Name>: <value>
...
<optional body>
# Lines end with CRLF (
). Headers are case-insensitive.
# A blank line (
) separates headers from body.Telnet / 原始 HTTP 调试
可以使用 nc 或 telnet(端口 80)或 openssl s_client(HTTPS)在 TCP 上直接发送原始 HTTP。这对调试非常有价值。在 HTTP/1.1+ 上必须包含 Host 头。两个空行终止请求。curl -v 显示包括头在内的网络格式对话。
# Manual HTTP request via netcat/nc
nc example.com 80
GET / HTTP/1.1
Host: example.com
# (press Enter twice to send blank line)
# Using openssl for HTTPS
openssl s_client -connect example.com:443
GET / HTTP/1.1
Host: example.com
# curl with --http1.1 to force version
curl -v --http1.1 https://example.com
curl -v --http2 https://example.com
curl -v --http3 https://example.comHTTP 方法
GET — 获取资源
GET 检索资源的表示。它必须是安全的(无副作用)且幂等的(可重复)。GET 请求可缓存、可加入书签。虽然规范允许请求体,但不建议使用——代理和 CDN 可能会剥离它。改用查询参数进行过滤。
# Basic GET
GET /api/users/42 HTTP/1.1
Host: api.example.com
Accept: application/json
# GET with query parameters
GET /api/users?role=admin&active=true HTTP/1.1
Host: api.example.com
# GET should be safe & idempotent
# - safe: no server state change
# - idempotent: repeating yields same result
# - cacheable: yes
# - body allowed but discouraged (some clients/servers reject)POST — 创建资源
POST 提交数据以进行处理。它用于创建由服务器分配 URI 的新资源(例如 /api/users → /api/users/43)。POST 既不安全也不幂等——提交两次可能创建两个资源。201 Created 响应应包含指向新资源的 Location 头。
# POST creating a new resource
POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 52
{"name": "Bob", "email": "[email protected]", "age": 30}
# Response typically 201 Created with Location header
HTTP/1.1 201 Created
Location: /api/users/43
Content-Type: application/json
{"id": 43, "name": "Bob"}
# POST is neither safe nor idempotent.
# Repeating may create duplicate resources.PUT — 替换资源
PUT 用请求体替换目标 URI 处的整个资源。它是幂等的——重复相同的 PUT 产生相同的最终状态。PUT 针对特定 URI(例如 /users/43),而 POST 针对集合。如果在 PUT 中省略某个字段,通常会将其删除(完全替换)。
# PUT replaces the entire resource at the given URI
PUT /api/users/43 HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 60
{"id": 43, "name": "Robert", "email": "[email protected]", "age": 31}
# Idempotent: sending the same PUT again yields the same state.
# If the resource doesn't exist, PUT may create it (server-dependent).
# Response
HTTP/1.1 200 OK
# or 204 No Content if no body returnedPATCH — 部分更新
PATCH 对资源应用部分更新,与 PUT 完全替换不同。最简单的形式是 JSON Merge Patch(RFC 7396):仅发送要更改的字段。JSON Patch(RFC 6902)使用操作数组(add、remove、replace、move、copy、test)。PATCH 默认不幂等,但 merge-patch 是幂等的。
# PATCH applies partial modifications
PATCH /api/users/43 HTTP/1.1
Host: api.example.com
Content-Type: application/merge-patch+json
Content-Length: 22
{"email": "[email protected]"}
# Only the email field is updated; other fields remain.
# JSON Patch (RFC 6902) - structured operations
PATCH /api/users/43 HTTP/1.1
Content-Type: application/json-patch+json
[
{"op": "replace", "path": "/email", "value": "[email protected]"},
{"op": "remove", "path": "/age"}
]DELETE — 删除资源
DELETE 删除目标资源。它是幂等的——两次删除同一资源应使服务器保持相同状态。常见的成功代码是 204(无请求体)、200(带有确认的请求体)或 202(异步删除)。大多数 API 需要认证。对于缺失的资源是否返回 404 存在争议——204 对幂等更安全。
# Delete a resource
DELETE /api/users/43 HTTP/1.1
Host: api.example.com
Authorization: Bearer <token>
# Successful responses:
HTTP/1.1 204 No Content # most common
HTTP/1.1 200 OK # if body returned
HTTP/1.1 202 Accepted # async deletion queued
# Idempotent: deleting an already-deleted resource
# should still return 204 (or 404 — debatable).HEAD 与 OPTIONS
HEAD 与 GET 相同,但服务器只返回头(无请求体)——适合在不下载请求体的情况下检查 Content-Length、Content-Type 或 Last-Modified。OPTIONS 询问允许哪些方法(Allow 头),并被浏览器用于 CORS 预检。两者都是安全且幂等的。
# HEAD: like GET but returns headers only (no body)
HEAD /api/users/42 HTTP/1.1
Host: api.example.com
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 128
# (no body)
# OPTIONS: describe communication options
OPTIONS /api/users HTTP/1.1
Host: api.example.com
HTTP/1.1 200 OK
Allow: GET, POST, HEAD, OPTIONS
Access-Control-Allow-Methods: GET, POST状态码
1xx 信息性
1xx 代码是信息性的,表示请求已收到,处理继续进行。100 Continue 让客户端检查是否发送大型请求体(与 Expect: 100-continue 头配合使用)。101 Switching Protocols 启用 WebSocket。103 Early Hints 让服务器在最终响应准备好之前提示浏览器预加载资源。
# 100 Continue - server received headers, client may send body
POST /upload HTTP/1.1
Host: example.com
Expect: 100-continue
Content-Length: 1048576
# Server replies:
HTTP/1.1 100 Continue
# (client now sends the request body)
# 101 Switching Protocols - used for WebSocket upgrade
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
# 103 Early Hints - preload resources before final response
HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style2xx 成功
2xx 代码表示成功。200 OK 是通用成功。201 Created 表示创建了新资源(带有 Location 头)。202 Accepted 表示请求已排队进行异步处理(例如长任务)。204 No Content 表示成功但无请求体——常用于 DELETE/PUT。206 Partial Content 返回资源的一部分(Range 请求)。
# 200 OK - standard success
HTTP/1.1 200 OK
# 201 Created - new resource created (POST/PUT)
HTTP/1.1 201 Created
Location: /api/users/43
# 202 Accepted - request queued for async processing
HTTP/1.1 202 Accepted
# 204 No Content - success, no body (DELETE, PUT)
HTTP/1.1 204 No Content
# 206 Partial Content - Range request result
HTTP/1.1 206 Partial Content
Content-Range: bytes 0-1023/20483xx 重定向
3xx 代码表示重定向。301/308 是永久的(可缓存,SEO 链接权重传递);302/307 是临时的。关键区别:301 和 302 历史上允许 POST→GET 转换(导致数据丢失),而 307 和 308 严格保留方法。304 Not Modified 在缓存有效时的条件请求中返回——不发送请求体。
# 301 Moved Permanently - cacheable, change bookmarks
HTTP/1.1 301 Moved Permanently
Location: https://newsite.com/page
# 302 Found - temporary redirect (don't update bookmarks)
HTTP/1.1 302 Found
Location: /login
# 304 Not Modified - cache is still valid (conditional GET)
HTTP/1.1 304 Not Modified
ETag: "abc123"
# 307 Temporary Redirect - preserves method (POST stays POST)
HTTP/1.1 307 Temporary Redirect
Location: /new-endpoint
# 308 Permanent Redirect - permanent, preserves method
HTTP/1.1 308 Permanent Redirect
Location: https://newsite.com/api4xx 客户端错误
4xx 代码表示客户端出错。400 Bad Request 是格式错误的输入。401 表示无/无效认证(必须包含 WWW-Authenticate)。403 表示已认证但缺少权限。404 是缺失资源。429 表示速率限制(包含 Retry-After)。其他常见代码:405 Method Not Allowed、409 Conflict、422 Unprocessable Entity。
# 400 Bad Request - malformed syntax
HTTP/1.1 400 Bad Request
Content-Type: application/json
{"error": "Invalid JSON in request body"}
# 401 Unauthorized - authentication required
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="api"
# 403 Forbidden - authenticated but not allowed
HTTP/1.1 403 Forbidden
# 404 Not Found - resource doesn't exist
HTTP/1.1 404 Not Found
# 429 Too Many Requests - rate limit hit
HTTP/1.1 429 Too Many Requests
Retry-After: 605xx 服务器错误
5xx 代码表示服务器失败。500 是未处理错误的统称(检查服务器日志)。501 表示服务器未实现该方法。502 表示代理/网关从上游收到错误响应。503 表示临时过载(使用 Retry-After)。504 表示上游超时。客户端可以用退避策略重试 502/503/504。
# 500 Internal Server Error - generic server failure
HTTP/1.1 500 Internal Server Error
# 501 Not Implemented - server doesn't support the method
HTTP/1.1 501 Not Implemented
# 502 Bad Gateway - upstream server returned invalid response
HTTP/1.1 502 Bad Gateway
# 503 Service Unavailable - temporary overload or maintenance
HTTP/1.1 503 Service Unavailable
Retry-After: 300
# 504 Gateway Timeout - upstream didn't respond in time
HTTP/1.1 504 Gateway Timeout状态码模式
一致的状态码映射使 API 可预测。使用 2xx 表示成功,并注意语义精确性(201 表示创建,204 表示无请求体)。使用 4xx 表示客户端错误,并选择最具体的代码(409 表示冲突,422 表示验证失败)。401 与 403 是最常见的混淆:401 = '你是谁?',403 = '我知道你是谁,但你不能做这件事'。
# REST API common mapping
GET /users -> 200
POST /users -> 201 (Created)
GET /users/42 -> 200 | 404
PUT /users/42 -> 200 | 201 (if created) | 404
PATCH /users/42 -> 200 | 404
DELETE /users/42 -> 204 | 404
# Validation errors
400 -> malformed JSON, missing required field
409 -> duplicate resource / version conflict
422 -> semantic validation failure (some APIs)
# Auth flow
401 -> no/invalid token (login required)
403 -> logged in but lacking permission
404 -> hide existence from unauthorized users
# Use 418 I'm a teapot for fun (RFC 2324 joke).请求头
常见请求头
常见请求头传达客户端身份(User-Agent)、所需响应格式(Accept 系列)、连接控制(Connection)、认证(Authorization)、状态(Cookie)和来源(Referer/Origin)。Host 在 HTTP/1.1+ 中是必需的,用于虚拟主机。Content-Type 和 Content-Length 描述任何请求体。
GET /api/data HTTP/1.1
Host: api.example.com # target host (mandatory in HTTP/1.1)
User-Agent: Mozilla/5.0 # client identity
Accept: application/json # desired response format
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Authorization: Bearer <token>
Cookie: session=abc123; theme=dark
Referer: https://example.com/
Origin: https://example.com
Content-Type: application/json
Content-Length: 42Accept 头(内容协商)
Accept 系列驱动内容协商。质量值(q,0-1)表示偏好——值越高越偏好。*/* 是通配符,匹配所有类型。服务器从其支持的类型中选择最佳匹配;如果都不匹配,则返回 406 Not Acceptable(尽管大多数服务器会回退到默认值而不是 406)。Brotli(br)和 zstd 提供比 gzip 更好的压缩。
# Accept: desired media types with quality (q) values
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
# Accept-Language: preferred languages
Accept-Language: en-US,en;q=0.9, zh-CN;q=0.8, fr;q=0.7
# Accept-Encoding: accepted compression algorithms
Accept-Encoding: gzip, deflate, br, zstd;q=0.9
# q=1.0 is default. Higher q = more preferred.
# */* matches any type.
# Server responds with 406 Not Acceptable if it can't satisfy.Authorization 与认证头
Authorization 携带凭据。Basic auth 在每个请求上发送 base64 编码的用户名:密码(始终使用 HTTPS)。Bearer 令牌是不透明字符串(通常是 JWT),用于 OAuth 2.0。自定义认证方案(X-API-Key)在 API 网关中很常见。Basic auth 的 base64 是编码,不是加密——没有 TLS 它不提供任何安全性。
# Basic Authentication (base64 of user:pass)
Authorization: Basic dXNlcjpwYXNz
# dXNlcjpwYXNz = base64("user:pass")
# Bearer Token (OAuth 2.0 / JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
# API Key in header (custom)
X-API-Key: abc123def456
# Proxy authentication
Proxy-Authorization: Basic dXNlcjpwYXNz
# WARNING: Basic auth sends credentials on every request.
# Always use HTTPS to prevent eavesdropping.User-Agent 与 Referer
User-Agent 标识客户端,但大多数浏览器为了向后兼容(历史嗅探)伪造 Mozilla/5.0。Referer(规范中拼写错误,从未更正)告诉服务器哪个页面链接到此请求——用于分析和防盗链保护。Origin 是 scheme+host+port,由浏览器在 CORS 请求和 POST 请求中发送。
# User-Agent identifies the client software
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
# Common browsers prepend "Mozilla/5.0" for historical compatibility
# (servers used to serve different content to different browsers)
# Referer: page that linked to this request
Referer: https://example.com/search?q=hello
# Origin: scheme + host + port (used by CORS)
Origin: https://example.com
# Note: "Referer" is the official spelling (misspelled in the original spec)条件请求头
条件头启用高效缓存和并发控制。If-None-Match(与 ETag 一起)和 If-Modified-Since(与 Last-Modified 一起)使 GET 成为条件请求——如果缓存有效,服务器返回 304。If-Match 和 If-Unmodified-Since 保护 PUT/PATCH 免受丢失更新(乐观并发)。If-Range 启用原子范围请求。
# Conditional GET - only fetch if changed
If-Modified-Since: Wed, 21 Oct 2023 07:28:00 GMT
If-None-Match: "abc123"
# If-Match / If-Unmodified-Since - for safe PUT/PATCH
If-Match: "abc123"
If-Unmodified-Since: Wed, 21 Oct 2023 07:28:00 GMT
# If-Range - for range requests (all-or-nothing)
If-Range: "abc123"
Range: bytes=0-1023
# Typical flow:
# 1. Server sends ETag/Last-Modified with response
# 2. Client sends If-None-Match/If-Modified-Since on next request
# 3. Server replies 304 if unchanged, 200 if changed自定义头与 X- 头
自定义头历史上使用 X- 前缀,但 RFC 6648 在 2012 年废弃了此约定。新头应去掉 X-(例如 Request-ID 而不是 X-Request-ID)。X-Forwarded-For 和 X-Forwarded-Proto 通过代理携带客户端信息(注意:可被伪造)。标准化替代方案是 Forwarded(RFC 7239)。Traceparent/Tracestate 启用分布式追踪(W3C)。
# X- prefixed headers (deprecated convention, but widely used)
X-Request-ID: 550e8400-e29b-41d4-a716-446655440000
X-Correlation-ID: abc-123
X-Forwarded-For: 203.0.113.1, 70.41.3.18
X-Forwarded-Proto: https
X-Real-IP: 203.0.113.1
X-RateLimit-Remaining: 42
# Modern recommendation: avoid X- prefix (RFC 6648)
# Use a namespace instead:
Request-ID: 550e8400-e29b-41d4-a716-446655440000
Traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
# Forwarded (RFC 7239) - standardized proxy info
Forwarded: for=203.0.113.1; proto=https; host=example.com响应头
常见响应头
常见响应头描述服务器(Server)、响应体(Content-Type、Content-Length)、连接控制(Connection)、缓存(Cache-Control、ETag、Last-Modified)、内容协商(Vary)、状态(Set-Cookie)和 CORS(Access-Control-*)。Date 是必需的,使用 GMT 的 RFC 1123 格式。