尝试将 POST 请求发送到 Nginx 服务器上的静态文件时,HTTP2 的奇怪行为。立即获得 200 响应,而无需在 HTTP2 上发送整个数据并在 HTTP1.1 上上传整个文件而没有任何问题。
当我将上传路径更改为“upload.php”时,在 HTTP2 和 1.1 上一切正常。当我们尝试将 POST 请求发送到“upload.bin”或“上传”HTTP2 上带有或不带有扩展名的静态文件时会出现问题。
<body>
<input type="file" id="file-input" />
<button id="upload-button">Upload File</button>
<div id=live></div>
<div id=live2></div>
<script type="text/javascript">
var live = document.getElementById('live');
var live2 = document.getElementById('live2');
document.querySelector('#upload-button').addEventListener('click', function() {
if(document.querySelector('#file-input').files.length == 0) {
alert('Error : No file selected');
return;
}
let file = document.querySelector('#file-input').files[0];
let allowed_mime_types = [ 'application/zip', 'image/png' ];
let data = new FormData();
data.append('file', document.querySelector('#file-input').files[0]);
let request = new XMLHttpRequest();
request.open('POST', 'upload');
request.upload.addEventListener("progress", progressHandler, function(e) {
});
request.send(data);
function progressHandler(event){
live.innerHTML = "Event.Loaded = " + event.loaded;
var percent = (event.loaded / event.total)*100;
live2.innerHTML = "Progress percent = " + percent;
}
});
在 Nginx 配置中处理发布到静态文件。
error_page 405 =200 $uri;
为什么 NGINX 对带有 HTTP2 的 POST 请求表现得像这样?
答案 0 :(得分:1)
这是故意的。
NGINX 知道您的 405 错误渲染器不需要任何正文,因此使用 HTTP,它会丢弃任何接收到的数据。这就是 HTTP1.1 的真正设计方式。
使用 HTTP2,它变得更聪明,它告诉对方中止发送数据,并发送结果页面。这样做是为了防止将互联网数据包浪费在无论如何都会被丢弃的数据上。
HTTP2 及更高版本的工作方式更智能,并且为已知事物浪费更少的数据(例如,如果您需要登录以上传文件,它只会尽快告诉客户端有是一个错误,而是等到您的完整文件上传完毕)
当你向 .php 文件发送请求时,php 进程接管了它,它没有办法立即返回结果,所以 NGINX 在显示错误之前将整个页面流式传输到 php,因为 PHP仅在收到文件后才开始执行页面上的代码,并且它可能会对 POST 请求执行某些操作