本页目录

HTTP/1.1

HTTP/1.1 的核心机制——持久连接、pipelining(理论好实践差)、chunked 编码、缓存协商——承载了 Web 二十年的流量。队头阻塞和连接数限制直接催生了 HTTP/2 的多路复用。

概述

HTTP/1.1(1997-2014)定义了 Web 的基础:请求-响应模型、状态码、缓存控制、持久连接。尽管 HTTP/2 和 HTTP/3 已在性能上大幅超越,HTTP/1.1 仍然是所有 HTTP 实现必须兼容的基线——每个 HTTP/2 连接都从 HTTP/1.1 Upgrade 开始。理解其消息格式、chunked 传输、CORS 跨域和缓存语义是 Web 开发的基础。

Message Format

HTTP-message = start-line *(header-field CRLF) CRLF [ message-body ]

Request:
  GET /api/v1/query?q=up HTTP/1.1
  Host: grafana.example.com
  Accept: application/json
  Accept-Encoding: gzip, br

Response:
  HTTP/1.1 200 OK
  Content-Type: application/json
  Content-Length: 42
  Cache-Control: max-age=3600

  {"status":"success"}

Status Code:
  1xx: Informational (100 Continue, 101 Switching Protocols)
  2xx: Success (200 OK, 201 Created, 204 No Content, 206 Partial Content)
  3xx: Redirection (301 Moved Permanently, 302 Found, 304 Not Modified, 307/308 redirect with method preserved)
  4xx: Client Error (400 Bad Request, 401 Unauthorized, 403 Forbidden, 404 Not Found, 429 Too Many Requests)
  5xx: Server Error (500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout)

Persistent Connections

HTTP/1.0: 每 request → 新 TCP 连接 → 3-way handshake overhead HTTP/1.1: Connection: keep-alive (default) — 复用同一个 TCP 连接发送多个 request

Pipelining (HTTP/1.1): 不等前一个 response → 连续发送多个 request。实践中很少使用 (server 必须按 order 回复 → HOL blocking, 代理兼容性差)。

Chunked Transfer Encoding

当 response body 的 size 不能在 header 中预知 (动态生成、流式数据):

HTTP/1.1 200 OK
Transfer-Encoding: chunked

1a\r\n
abcdefghijklmnopqrstuvwxyz\r\n
0d\r\n
Hello, World\r\n
0\r\n
\r\n

格式: <chunk size in hex>\r\n<chunk data>\r\n
最后 chunk: 0\r\n + optional trailer headers + \r\n

CORS

Brower 的 same-origin policy 阻止页面访问不同源的资源。CORS 允许 server 声明例外:

Simple Request (GET with simple headers):
  GET /api/data HTTP/1.1
  Origin: https://chat.example.com           ← browser auto-adds

  HTTP/1.1 200 OK
  Access-Control-Allow-Origin: https://chat.example.com
  Vary: Origin

Preflight (before non-simple requests):
  OPTIONS /api/data HTTP/1.1
  Origin: https://chat.example.com
  Access-Control-Request-Method: POST
  Access-Control-Request-Headers: Content-Type

  HTTP/1.1 204 No Content
  Access-Control-Allow-Origin: https://chat.example.com
  Access-Control-Allow-Methods: GET, POST, PUT
  Access-Control-Allow-Headers: Content-Type
  Access-Control-Max-Age: 86400             ← 缓存 preflight 24h

Credentials (cookies, HTTP auth):
  Access-Control-Allow-Credentials: true     ← 不能与 wildcard origin "*" 共用
  Access-Control-Allow-Origin: https://chat.example.com  ← 必须是具体值

HTTP Caching

Request:
  Cache-Control: max-age=3600                 ← 期望 3600s 内 fresh
  If-None-Match: "abc123"                     ← 条件请求 (ETag)
  If-Modified-Since: Tue, 01 Jan 2025 00:00:00 GMT

Response:
  Cache-Control: public, max-age=86400, immutable
    public:        CDN/中间代理可以缓存
    private:       只能 browser 缓存 (含 Authorization or cookie)
    max-age:       fresh lifetime (从 response date 开始)
    immutable:     资源内容永不变 (fingerprinted asset) → 不 revalidate
    no-cache:      可以用缓存但必须先 revalidate (If-None-Match)
    no-store:      不存任何缓存 (含 private caches)
    must-revalidate: 过期后必须 revalidate (即使 max-stale)
  ETag: "abc123"                               ← 资源版本 (content hash)
  Last-Modified: Tue, 01 Jan 2025 00:00:00 GMT

304 Not Modified:
  条件请求 If-None-Match 匹配 → server 回 304 (body 为空) → client 继续用缓存

参考

  • RFC: 7230-7235, 7234
  • MDN: developer.mozilla.org/en-US/docs/Web/HTTP

Keywords: HTTP/1.1, keep-alive, chunked, CORS, preflight, cache-control, ETag, conditional request