Nginx处理HTTP请求

标准的 HTTP 请求从开始到结束包括请求报文和响应报文。

请求报文是客户端向服务端发起请求时告知服务端请求的方式、相关属性和请求内容的数据包,由请求行、请求头、请求体组成,这里以百度首页的请求为例,HTTP请求头结构如下图所示。

HTTP 请求头结构
图:HTTP 请求头结构

请求行是请求头内容的第一行,包括请求方法 GET,请求的 URI 地址 https://www.baidu.com,请求的协议及版本号 HTTP/1.1。

请求头还包含此次请求所设定的若干属性字段,属性字段由属性名称和属性值组成,如浏览器信息 User-Agent 等。

请求体则是请求数据,该请求是无参数的 GET 方法,请求体中无内容。

常见的请求头属性如下表所示。

属性名称 属性值样例 属性说明
Host www.baidu.com 记录用户请求的目标主机名,常用于服务端虚拟主机的区分,对应 Nginx 的 server_name 指令的配置
Accept text/html, application/xhtml+xml 描述客户端能够接收服务端返回的数据类型,Nginx 会通过 types 指令域中的内容做匹配
Cookie BD_HOME=1; sugstore=1 客户端当前连接的所有 cookie
Referer https://www.baidu.com 表示当前连接的上一个来源 URI
Cache-Control no-cache 当前客户端缓存机制的控制,可通过更多的属性值参数进行缓存控制
Connection keep-alive 表示是否需要启用保持连接机制,HTTP/1.1 默认启用保持连接
If-None-Match W/ "50b1c1d4f775c61:df3" 与页面响应头中 etag 的属性值配合使用,将 etag 的内容提交给服务端,用以判断请求内容是否已经被修改,若未被修改,则返回状态码 304,客户端使用本地缓存
if_modified_since -- 当前请求 URI 页面本地缓存的最后修改时间。服务器会将实际文件的修改时间与该参数值进行比较,若一致,则返回 304,客户端读取本地缓存;若不一致,则返回服务端文件的内容

响应报文是服务端处理客户端请求后返回客户端的数据,数据包括响应行、响应头、响应体 3 个部分,HTTP 响应头结构如下图所示。

HTTP 响应头结构
图:HTTP 响应头结构

响应行是响应头内容的第一行,包含报文协议及版本号 HTTP/1.1、响应状态码 200、响应状态描述 OK。

响应头则包含服务端处理完请求后响应设定的若干属性字段,如 set-cookie 信息等。

响应体为返回的处理结果,本次请求的响应体是 HTML 页面数据。

HTTP 响应状态码是响应报文中对 HTTP 请求处理结果的重要标识,响应状态码是由 RFC 2616 规范定义的,并由互联网号码分配局(Internet Assigned Numbers Authority)维护,状态码可以分为以下 5 个类别。
  • 1××(消息):表示服务端已经接收到请求,正在进行处理;
  • 2××(处理成功):表示服务端已经正确处理完客户端的 HTTP 请求;
  • 3××(重定向):服务端接收到 HTTP 请求,并将其 HTTP 请求重定向到客户本地或其他服务器进行处理;
  • 4××(客户端请求有误):客户端提交的请求不符合规范或未被授权、禁止访问等;
  • 5××(服务端处理出错):服务端无法正常完成请求操作,如超时等。

常见的响应头属性如下表所示。

属性名称 属性值样例 属性说明
Content-Type text/html; charset=utf-8 告知客户端返回数据的类型
Connection keep-alive 告知客户端是否启用保持连接机制
Cache-Control no-cache 告知客户端对缓存机制的控制
ETag "50b1c 1d4f775c61:df3" 当前响应数据的实体标签值,用于在客户端与服务端提交相同请求时判断请求内容是否有修改
Location https://map.baidu.com/  告知客户端跳转到指定的 URI
Set-Cookie username=john.wang 通知客户端修改本地 cookie 内容

当 Nginx 接收 HTTP 请求后,处理相关的配置指令如下表所示。

指令 作用域 默认值 指令值选项 指令说明
ignore_invalid_headers http, server on on 或 off 忽略请求头中的无效属性字段,请求头属性字段中,属性名称默认由英文字符、数字和连接符组成,不符合此标准的属性名均为无效属性名。当指令值为on时,不对无效的属性名称进行过滤
underscores_in_headers http, server off on 或 off 请求头中属性名称的定义中“_”是无效连接符,启用该指令后,“_”将被认为是有效的连接符。如果该指令值为 off,则按照 ignore_invalid_headers 指令的配置进行处理
client_header_buffer_size http, server 1k -- 设置存放读取客户端请求头的缓冲区的大小,默认值为1K,当请求头的数据因cookie过长等其他原因超过所设定的大小时,会按照large-client header buffers的指令配置进行处理
large_client_header_buffers http, server 48k -- 当客户请求头的大小超过 client_header_buffer_size 指令设置的值时,会将超出的部分转移到该缓冲区中。在默认配置下,超大请求头第一次可分配到一个 8KB 的缓冲区块,请求行的大小不能超过该缓冲区块的大小,否则将返回 414 错误。超出 8KB 的请求头会被循环转移到新的缓冲区块中,最多转移 4 次,当超过该值时,则会返回 400 错误
client_header_timeout http, server 60s -- 读取客户端请求头的最大超时时间
request_pool_size http, server 4k -- Nginx 开始处理请求时,会为每个请求分配一个 4KB 大小的内存池,以减少内核对小块内存的分配次数,HTTP 请求结束后会回收为其分配的内存池
client_max_body_size http, server, Location 1m -- HTTP 请求时,请求体的最大值。当请求头中属性 Content-Length 的大小超过指令配置时,返回状态码 408
client_body_buffer_size http, server, location -- -- 设置读取客户请求体的缓冲区大小,当请求体的大小超过该设定值后,会按照 client_body_in_single_buffer 指令的配置选择部分或全部写入 client_body_temp_path 指令设定的文件中。默认配置下,32 位系统下缓冲区的大小是 8KB,64 位系统下缓冲区的大小是 16KB
client_body_in_file_only http, server, location off off 或 clean 或 on 默认情况下是优先使用缓存,在请求体超出请求体缓冲区的大小时再写入文件。启用该指令后将禁用缓冲区,请求体会被直接写入 client_body_temp_path 指令设定的文件中
client_body_temp_path http, server, location client_body_temp_path_client_body_temp -- 请求体被写入文件的临时目录
client_body_timeout http, server, location 60s -- 当 HTTP 请求建立连接后,客户端在超过设定时间后仍未发送请求体内容到服务端,则 Nginx 认为请求体超时,将返回响应状态码 408
if_modified_since http, server, location exact off 或 exact 或 before 在请求头中存在属性if modified since时,关闭或设置客户端缓存文件修改时间的服务端校验功能
etag http, server, location on on 或 off etag(Entity Tag),用于在响应头中返回文件实体标签,与同一文件的下一次请求头中 If-None-Match 属性值组合检查文件是否被修改,未修改则返回响应状态码 304,否则返回最新的文件内容
max_ranges http, server, location -- -- 默认为不限制大小,当客户端以 byte-range 方式获取数据请求时,该指令限定了允许的最大值。当指令值为 0 时,则关闭以 byte-range 方式获取数据的功能
types http, server, location -- -- 被请求文件扩展名与 MIME 类型映射表
types_hash_max_size http, server, location 1024 -- 设定 MIME 类型哈希表的大小
types_hash_bucket_size http, server, location -- -- 设定 MIME 类型哈希桶的大小,默认值与 CPU 缓存行的大小一致,有 32、64、128(单位:字节)3 个值
error_page http, server, location -- -- 当 HTTP 请求发生错误时,可以根据响应状态码定义一个返回的页面或执行跳转
recursive_error_pages http, server, location off off 或 on 当使用 error_pages 设定多层内部访问时,仍可处理上一层级返回的响应状态码
server_tokens http, server, location on on 或 off 默认在错误信息响应头中增加属性字段“Server”以标识 Nginx 的版本号
msie_padding http, server, location on on 或 off 在响应状态大于或等于 400 时,会在响应报文中添加注释,使响应报文大小达到 512 字节。仅适用于 msie 客户端

配置样例如下:

http {
    ignore_invalid_headers off;
    underscores_in_headers on;
    client_header_buffer_size 2k;
    large_client_header_buffers 10 8k;
    client_header_timeout 180s;
    request_pool_size 4k;
    client_max_body_size 100m;
    client_body_in_file_only on;
    client_body_temp_path /tmp/nginx/client_temp 1 2;
    client_body_timeout 120s;
    if_modified_since before;
    etag off;
    max_ranges 1024 ;
    types_hash_max_size 2048;
    types_hash_bucket_size 64;
    error_page 404             /404.html;
    error_page 500 502 503 504 /50x.html;
    error_page 404 = @fallback;
    location @fallback {
        proxy_pass http://backend;
    }
    error_page 404 =200 /empty.gif;
    location /download/ {
        types {
            application/octet-stream yaml;
        }
        default_type application/octet-stream;
    }
    proxy_intercept_errors on;          # 当上游服务器返回非200状态码时,返回代理服务器处理
    recursive_error_pages on;           # 启用多级错误跳转功能
    location / {
        error_page 404 = @fallback;     # 当前URL请求为404时执行内部请求@fallback
    }
    location @fallback {
        proxy_pass http://backend;      # 当前所有请求代理到上游服务器backend
        error_page 502 = @upfallback;   # 当上游服务器返回502状态码时,执行内部请求@upfallback
    }
    location @upfallback {
        proxy_pass http://newbackend;   # 当前的所有请求代理到上游服务器newbackend
    }
    server_tokens off;
    msie_padding off;
}