Java实现个人Web服务器无法响应HEAD请求报错如何解决
报错原因
- HTTP协议明确规定HEAD请求仅需要返回和对应GET请求完全一致的响应头,禁止返回任何响应体内容,哪怕是空字节也不允许。
- JDK内置的
sun.net.httpserver实现对HEAD请求做了特殊校验:调用sendResponseHeaders之后,如果尝试向响应输出流写入任何内容,底层的PlaceholderOutputStream会直接抛出异常,你看到的response headers not sent yet是校验触发后的错误提示。 - 你代码中同时设置了
Transfer-encoding: chunked和固定Content-Length,两个响应头本身违反HTTP规范,GET请求下底层实现做了兼容未报错,但HEAD请求的严格校验触发了问题。
修复方案
修改逻辑区分HEAD和GET请求的处理,HEAD请求仅发送响应头不写响应体,同时删除冲突的响应头,修改后的代码参考如下:
public void writeResponse(SettingModal settingModal) { try { // 公共响应头HEAD和GET完全一致 response.getResponseHeaders().set("Server", "utux HttpServer"); response.getResponseHeaders().set("Connection", "close"); response.getResponseHeaders().set("Content-Type", ContentType.HTML); // 替换为你实际要返回的响应内容的字节长度,HEAD和GET的Content-Length必须一致 byte[] responseContent = "<html><body>你的页面内容</body></html>".getBytes(StandardCharsets.UTF_8); int contentLength = responseContent.length; response.getResponseHeaders().set("Content-Length", String.valueOf(contentLength)); // 发送响应头,第二个参数传实际内容长度即可 response.sendResponseHeaders(HttpStatus.SC_OK, contentLength); // 仅GET请求需要写入响应体 if ("GET".equals(requestHeader.getMethod())) { response.getResponseBody().write(responseContent); response.getResponseBody().flush(); } response.getResponseBody().close(); } catch (IOException e) { e.printStackTrace(); } }
额外注意点
- 如果你的响应是动态生成的不确定长度,可以保留
Transfer-encoding: chunked,同时把sendResponseHeaders的第二个参数设为0即可,不需要再设置Content-Length头。 - 不要同时设置
Transfer-encoding: chunked和Content-Length,两个响应头互斥,会导致客户端解析异常。
内容的提问来源于stack exchange,提问作者mohammad
相关产品推荐
相关产品推荐

