鉴于此简单的网络服务器代码:
console.log('starting');
var server = require('http').createServer();
server.on('connection',function(socket){console.log('*server/connection');});
server.on(
'request',
function(request, response){
console.log('*server/request');
request.on(
'data',
function(chunk){
console.log('*request/data');
// <!> How do I abort next data calls from here?
}
);
request.on(
'readable',
function(chunk){
console.log('*request/readable');
// <!> How do I abort next readable calls from here?
}
);
request.on(
'end',
function(){
console.log('*request/end');
response.writeHead(200,"OK");
response.write('Hello');
response.end();
}
);
request.on('close',function(){ console.log('*request/close'); } );
request.on('error',function(){ console.log('*request/error'); } );
}
);
server.on('close',function(){console.log('server/close');});
server.on('checkContinue',function(request, response){console.log('*server/checkContinue');});
server.on('connect',function(request, socket, head){console.log('*server/connect');});
server.on('upgrade',function(request, socket, head){console.log('*server/upgrade');});
server.on('clientError',function(exception, socket){console.log('*server/clientError');});
server.listen(8080);
console.log('started');
Run Code Online (Sandbox Code Playgroud)
当提交POST或FILE时,我的on数据功能会被触发一次或多次.有时候(就像发送了一个可怕的大文件)我想在数据事件上取消它并触发用户的on end功能(稍后我会显示"你的帖子/文件太大了").我该怎么做?
jos*_*736 32
在这里做正确的,符合规范的事情就是尽早发送HTTP 413响应 - 也就是说,一旦检测到客户端发送的字节数多于您想要处理的字节数.在发送错误响应后是否终止套接字取决于您.这符合RFC 2616 :(强调添加)
413请求实体太大
服务器拒绝处理请求,因为请求实体大于服务器愿意或能够处理的请求实体.服务器可以关闭连接以防止客户端继续请求.
接下来发生的事情并不理想.
如果您打开套接字,所有浏览器(Chrome 30,IE 10,Firefox 21)将继续发送数据,直到整个文件上传为止.然后,只有这样,浏览器才会显示您的错误消息.这真的很糟糕,因为用户必须等待整个文件完成上传,才发现服务器拒绝了它.它也浪费你的带宽.
浏览器的当前行为违反了RFC2616§8.2.2:
发送消息体的HTTP/1.1(或更高版本)客户端应该在发送请求时监视网络连接的错误状态.如果客户端看到错误状态,它应该立即停止传输正文.如果正在使用"分块"编码发送正文(第3.6节),则可以使用零长度块和空拖车来过早标记消息的结尾.如果正文前面有Content-Length标头,则客户端必须关闭连接.
如果您在发送HTTP响应413后,立即关闭插座,所有的浏览器显然会立即停止上传,但他们 大多数,目前有一个"连接重置"的错误(或类似),没有任何HTML您可能会在响应中发送.
同样,这可能违反了规范(允许服务器提前发送响应并关闭连接),但我不希望浏览器在这里很快修复.
更新:自4月15日起,Chrome 可能会在您提前关闭连接时显示您的413 HTML.这仅适用于浏览器在Linux和Mac OS X上运行的情况.在Windows上,Chrome仍会显示ERR_CONNECTION_RESET网络错误,而不是您发送的HTML.(IE 11和Firefox 37继续在所有平台上显示网络错误.)
因此,您对传统普通HTTP上传的选择是:
显示友好的错误消息,但仅在上载运行完成后显示.这浪费了时间和带宽.
失败很快,但让用户对一个神秘的浏览器错误屏幕感到困惑.
这里最好的选择可能是使用AJAX上传器,您可以更好地控制用户体验.你仍然应该提供一个传统的上传表格作为后备,我会使用"快速失败"选项(关闭套接字)来防止浪费时间和带宽.
以下是一些示例代码,如果它接收的请求超过1 kB,则会终止该请求.我正在使用Express,但同样适用于node的vanilla HTTP库.
注意:实际上,您应该使用强大的 多方来处理您的上传(这是Connect/Express使用的),并且它有自己的方式来监控上传数据.
var express = require("express")
, app = express();
app.get('/', function(req, res) {
res.send('Uploads > 1 kB rejected<form action="/upload" method="post" enctype="multipart/form-data"><input type="file" name="file"><input type="submit"></form>');
});
app.post('/upload', function(req, res) {
var size = 0;
var gotData = function(d) {
size += d.length; // add this chunk's size to the total number of bytes received thus far
console.log('upload chunk', size);
if (size > 1024) {
console.log('aborting request');
req.removeListener('data', gotData); // we need to remove the event listeners so that we don't end up here more than once
req.removeListener('end', reqEnd);
res.header('Connection', 'close'); // with the Connection: close header set, node will automatically close the socket...
res.send(413, 'Upload too large'); // ... after sending a response
}
};
var reqEnd = function() {
res.send('ok, got ' + size + ' bytes');
}
req.on('data', gotData);
req.on('end', reqEnd);
});
app.listen(3003);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7855 次 |
| 最近记录: |