如何在文件读取出错后发送HTTP 500错误响应头
解决读取文件错误时发送HTTP 500响应的问题
嘿,咱们先揪出原代码里的核心问题:你在还没确认文件能不能正常读取的时候,就已经把200 OK的响应头发给客户端了!HTTP协议里响应头一旦发出去就没法修改,这时候再碰到文件读取错误,只能在已经标记为成功的响应里塞错误内容,完全不符合你要返回500的需求。
正确的思路应该是:先尝试获取文件流,等确认流能正常工作(没出错),再发送200响应头并把流pipe到socket;如果一开始获取流就失败了,直接发送500响应头然后结束连接就行。
下面是调整后的代码:
const writeResponse = function(file: string, s: Socket){ const fileStream = getStream(file); // 先绑定错误监听,别错过流创建时的异步错误 fileStream.once('error', function (e: any) { // 发送500响应头+错误详情 s.write([ 'HTTP/1.1 500 Cannot read file', 'Content-Type: text/plain; charset=UTF-8', 'Connection: close', // 出错后直接关闭连接更合理 ].join('\n') + '\n\n'); s.end('Error: ' + (e.stack || e.message || util.inspect(e))); }); // 等流成功打开(确认文件能读),再发送200响应头 fileStream.once('open', function() { s.write([ 'HTTP/1.1 200 OK', 'Content-Type: text/javascript; charset=UTF-8', 'Content-Encoding: UTF-8', 'Accept-Ranges: bytes', 'Connection: keep-alive', ].join('\n') + '\n\n'); fileStream.pipe(s); }); };
几个关键改动点:
- 调换执行顺序:先创建文件流、绑定错误监听,确认流没问题了再发送200头,彻底避免提前发错状态码的问题。
- 错误时直接返回500:在错误回调里直接构造500的响应头,顺便把连接设为
close——毕竟出错了还保持长连接没啥实际意义。 - 简化错误监听逻辑:原代码在pipe前后都加了错误监听,其实只要在流创建时监听一次就行,因为pipe过程中的错误会自动冒泡到原流上,不用重复处理。
另外还要提个小细节:如果你的getStream是同步创建流的(比如Node.js里的fs.createReadStream虽然后续错误是异步触发,但有些自定义方法可能会同步抛错),那得加个try-catch来覆盖同步错误场景:
const writeResponse = function(file: string, s: Socket){ let fileStream; try { fileStream = getStream(file); } catch (e: any) { // 处理同步抛出的错误 s.write([ 'HTTP/1.1 500 Cannot read file', 'Content-Type: text/plain; charset=UTF-8', 'Connection: close', ].join('\n') + '\n\n'); s.end('Error: ' + (e.stack || e.message || util.inspect(e))); return; } fileStream.once('error', function (e: any) { s.write([ 'HTTP/1.1 500 Cannot read file', 'Content-Type: text/plain; charset=UTF-8', 'Connection: close', ].join('\n') + '\n\n'); s.end('Error: ' + (e.stack || e.message || util.inspect(e))); }); fileStream.once('open', function() { s.write([ 'HTTP/1.1 200 OK', 'Content-Type: text/javascript; charset=UTF-8', 'Content-Encoding: UTF-8', 'Accept-Ranges: bytes', 'Connection: keep-alive', ].join('\n') + '\n\n'); fileStream.pipe(s); }); };
这样不管是同步还是异步的文件读取错误,都能正确发送500响应头,不会再出现先返回200再塞错误内容的尴尬情况了。
内容的提问来源于stack exchange,提问作者Alexander Mills
相关产品推荐
相关产品推荐

