为何C#简易Web服务器返回404时浏览器报net::ERR_HTTP_RESPONSE_CODE_FAILURE
C# 简易Web服务404响应触发
net::ERR_HTTP_RESPONSE_CODE_FAILURE问题排查 问题现象
- 服务返回除404外的所有HTTP状态码时,浏览器交互正常
- 仅返回404状态码时,浏览器直接抛出
net::ERR_HTTP_RESPONSE_CODE_FAILURE错误,控制台仅提示资源加载失败,不会显示正常站点可见的GET /xxx 404 (Not Found)日志 - 已排查状态行拼写错误无异常,抓包获取的异常404响应报文如下:
HTTP/1.1 404 Not Found Date: Server: MADSC Content-Length: 196 Content-Type: text/html
问题根因
结合提供的服务端实现代码,问题来自两处不符合HTTP规范的逻辑:
- 响应体发送逻辑缺失
WriteToStream方法的分支判断存在漏洞:当响应内容来自内存字节数组(data字段)时,仅将生成的HTTP头部写入网络流,完全没有把data的实际字节内容写入流中。对应有问题的代码片段:
这会导致实际发送的响应体长度为0,但头部声明的int dataSize = data.Length; httpHeaders = GenerateHttpHeaders(dataSize); WriteHttpHeadersToStream(httpHeaders, stream); // 此处缺少将data字节数组写入网络流的逻辑Content-Length是data数组的实际长度(示例中为196)。浏览器接收头部后,会按照声明长度等待剩余的响应体内容,最终因等待超时、连接提前中断判定响应非法。
其余状态码未触发问题的原因:测试时多走了本地文件读取的分支,文件内容会正常通过fs.CopyTo(stream)写入流中,Content-Length和实际内容长度匹配,未触发校验 - HTTP报文格式不合规
GenerateHttpHeaders方法中,所有头部行的结束符使用了单独的\n(LF),不符合HTTP/1.1规范要求的\r\n(CRLF)行结束符。多数浏览器对2xx类的成功响应会兼容这类格式偏差,但对错误状态码的响应会严格校验格式,一旦发现分隔符不符合规范,会直接判定响应报文非法。
此外,头部中的Date字段为空值,不符合HTTP规范对必填头字段的要求,也会触发严格模式下的校验拦截。
修复方案
- 修正头部行结束符:将
GenerateHttpHeaders方法中所有拼接的换行符从\n替换为\r\n,符合HTTP/1.1规范 - 补全内存响应的发送逻辑:在写入HTTP头部后,调用
stream.Write(data, 0, data.Length),将内存中的响应体内容写入网络流,确保实际发送的体长度和Content-Length声明值完全一致 - 补全
Date头取值:使用DateTime.UtcNow.ToString("R")生成标准GMT格式的时间字符串,替换原本空值的Date字段 - 修复后可通过
curl -v发送测试请求,确认响应头格式、响应体长度与声明值完全匹配
内容的提问来源于stack exchange,提问作者Luk 64
相关产品推荐
相关产品推荐

