问:get请求太长报400的错误,如何解决?生成系统中经常偶现此问题
问:get请求URL的长度是谁限制的?
问:每一个cookie的value的大小还是同域下cookie的个数做的限制?
现象:出现 400 Bad request
状态码400:客户端请求有语法错误,不能被服务器所理解。
问题:request header过大
一个HTTP请求报文由请求行(request line)、请求头部(header)、空行和请求体4个部分组成。
谁对request header 大小做限制?
在HTTP规范RFC-2616中有这样一段描述:
The HTTP protocol does not place any a priori limit on the length of a URI. Servers MUST be able to handle the URI of any resource they serve, and SHOULD be able to handle URIs of unbounded length if they provide GET- based forms that could generate such URIs. A server SHOULD return 414 (Request-URI Too Long) status if a URI is longer than the server can handle (see section 10.4.15).
Note: Servers ought to be cautious about depending on URI lengths above 255 bytes, because some older client or proxy implementations might not properly support these lengths.
HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URI长度进行限制,只是说如果server无法处理太长的URI,可以通过返回414状态码。
规范中虽然未对GET请求的长度做出明确的规定,但是在浏览器和应用服务器中对GET请求却做出限制或者相关的可配置:
- Chrome:对Google浏览器URL的最大长度为8182个字符。
- IE:对IE浏览器URL的最大长度为2083个字符。若超出这个数字,提交按钮没有任何反应。
- Firefox:对Firefox浏览器URL的最大长度为65536个字符。
- Safari: 对Safari浏览器URL的最大长度为80000个字符。
- Apache能接受url长度限制为8192字符
- nginx可以通过修改配置来改变url请求串的url长度限制:
- client_header_buffer_size 默认值:1k
- large_client_header_buffers默认值:4 8k
浏览器限制更多还是服务器限制更多?
实验分析
实验结论:浏览器允许的request header大小一般情况比Nginx服务器允许的大
测试方式:设置同样大小的cookie,通过浏览器直接访问服务器与通过浏览器先访问到Nginx再代理到服务器做对比得出。
const http = require('http');
const url = require('url');
const fs = require('fs-extra');const server = http.createServer(async (req, res) => {if (req.url === '/index.html') {console.log(req.headers);const html = await fs.readFile('./index.html', 'utf8');const cookieArr = [];for (let i = 0; i < 10; i++) {cookieArr.push(`cookie${i}=${Array.from({ length: 80 }, (v, i) => 'abcdefghijklmnopq' + i).join('')}value${i}; `);}res.writeHead(200, {'Content-Type': 'text/html','Set-Cookie': cookieArr});res.end(html);}if (req.url.startsWith('/postMethod')) {console.log('post');res.end('post');}
});
server.listen('3000', '127.0.0.1', () => {console.log('server runing...');
});
结论
过浏览器直接访问服务器的没有问题。
通过Nginx转发的存在问题
修改Nginx配置
-
client_header_buffer_size
client_header_buffer_size size;
Default: client_header_buffer_size 1k;
Context: http, server -
large_client_header_buffers
Syntax: large_client_header_buffers number size;
Default: large_client_header_buffers 4 8k;
Context: http, server
解决方案总结:
- cookie要设置合理,不能太大,个数不能太多
- 合理设置时效性,max-age,expires
- get请求参数过长,出现参数丢失情况
- Nginx上修改允许request header头大小配置,很明显,当前的ng默认配置已不能满足需求。
- 临时解决方案:让用户清除cookie。影响:用户需要重新登录