You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 01:06:07