最近项目上遇到一个问题,某个 http 请求会返回 413 的状态码,一般来讲,这个问题是很好解决的, 网上有非常多的解决方案,但是我依然花了很长的时间找到问题根源,所以我觉得可以把这个过程记录下来。
首先我们得了解 http 的 413 状态码代表什么意思,根据官方文档:
The 413 (Payload Too Large) status code indicates that the server is refusing to process a request because the request payload is larger than the server is willing or able to process. The server MAY close the connection to prevent the client from continuing the request. If the condition is temporary, the server SHOULD generate a Retry-After header field to indicate that it is temporary and after what time the client MAY try again.
简单来说, 响应状态码 413 Payload Too Large
表示请求主体的大小超过了服务器愿意或有能力处理的限度,服务器可能会关闭连接以防止客户端继续发送该请求。
那么服务器如何决定可以处理的请求主题的限度呢?服务器一般会是指代理服务器,如 nginx,也可能是 node、php 搭建的处理请求的 web 服务器。对于我们的项目来讲,是通过 nginx 做请求的转发,然后用 node 服务来处理 实际的请求。
location ^~ /test/ {
# 处理数据的node服务
proxy_pass http://127.0.0.1:5100/;
}
那么会是 nginx 的配置问题么?通过 nginx 的日志我们确实发现了有很多 413 状态码的请求,有可能是 nginx 的
配置存在问题。nginx 的 ngx_http_core_module
提供一个叫 client_max_body_size
的配置选项,它的作用是
控制客户端发送的请求体的最大 size,超过这个 size 就会返回 413 的状态码。
Syntax: client_max_body_size size;
Default:
**client_max_body_size** 1m;
Context: http, server, location
Sets the maximum allowed size of the client request body, specified in the “Content-Length” request header field. If the size in a request exceeds the configured value, the 413 (Request Entity Too Large) error is returned to the client. Please be aware that browsers cannot correctly display this error. Setting size to 0 disables checking of client request body size.
它的默认值是 1M,但是我们实际请求的 Content-Length
却只有几十 kb 而已,远没有达到最大限额,所以网上各种
增加 client_max_body_size
值的方式是行不通的。
那问题会出在哪里呢?打开 nginx 错误信息的 debug 模式,可以看到更具体的错误信息:
error_log /var/log/nginx/error.log debug;
Output:
/var/log/nginx/error.log:2465762:2019/01/11 10:04:02 [debug] 21213#21213: *323609 http proxy status 413 "413 Payload Too Large"
/var/log/nginx/error.log:2465769:2019/01/11 10:04:02 [debug] 21213#21213: *323609 HTTP/1.1 413 Payload Too Large
/var/log/nginx/error.log:2465780:2019/01/11 10:04:02 [debug] 21213#21213: *323609 http proxy filter init s:413 h:0 c:0 l:24
/var/log/nginx/error.log:2466634:2019/01/11 10:04:04 [debug] 21213#21213: *323618 http proxy status 413 "413 Payload Too Large"
/var/log/nginx/error.log:2466641:2019/01/11 10:04:04 [debug] 21213#21213: *323618 HTTP/1.1 413 Payload Too Large
在这里可以看到一个信息是 http proxy status 413
,既然 nginx 对请求做了反向代理,实际处理请求的是 node server,那会不会是 node 服务返回的 413 状态码呢?通过分析 node 服务的代码,我们发现 node
服务引入了一个叫 koa-bodyparser
的中间件,用于解析 http 请求体,在它的 wiki 里面发现了这样一个配置:
formLimit: limit of the urlencoded body. If the body ends up being larger than this limit, a 413 error code is returned. Default is 56kb.
而我们出问题的接口的content-length
都超过了 56 KB,因此提高这个值的配置后,重新部署代码就解决了 413 的问题。
comments powered by Disqus