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

Spring Boot 3.4.0升级后HEAD响应丢失Content-Length头如何恢复?

Spring Boot 3.4.0 HEAD请求丢失Content-Length头的修复方案

问题根源

Spring Boot 3.4.0依赖的Spring Framework 6.2对HEAD请求的处理逻辑做了变更:当返回ResponseEntity<Void>时,框架会自动移除Content-Length头——因为Void类型被判定为无响应体,框架默认认为HEAD请求的Content-Length应对应GET请求的响应体大小,但我们这里是手动设置的资源元数据大小,框架的自动处理覆盖了自定义头。

可行修复方案

方案1:替换ResponseEntity为非Void类型

将返回类型改为ResponseEntity<byte[]>,并返回空数组作为响应体,这样框架会保留手动设置的Content-Length头:

@RequestMapping(method = HEAD)
@ResponseStatus(HttpStatus.OK)
public ResponseEntity<byte[]> details() {
    FileMetadata fileMetadata = getFileMetadata();
    return ResponseEntity.ok()
            .headers(responseHeaders -> {
                responseHeaders.setContentLength(fileMetadata.size());
                responseHeaders.setLastModified(fileMetadata.lastModified());
            })
            .body(new byte[0]);
}

方案2:自定义过滤器强制保留头

创建一个过滤器,在响应提交前手动保留Content-Length头:

@Component
public class PreserveContentLengthFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (HttpMethod.HEAD.matches(request.getMethod())) {
            ContentCachingResponseWrapper wrappedResponse = new ContentCachingResponseWrapper(response);
            filterChain.doFilter(request, wrappedResponse);
            
            String contentLength = wrappedResponse.getHeader(HttpHeaders.CONTENT_LENGTH);
            if (contentLength != null) {
                response.setHeader(HttpHeaders.CONTENT_LENGTH, contentLength);
            }
            
            wrappedResponse.copyBodyToResponse();
        } else {
            filterChain.doFilter(request, response);
        }
    }
}

方案3:配置Spring MVC内容处理策略

在配置类中调整HttpMessageConverter的行为,允许Void响应体保留Content-Length头:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Bean
    public HttpMessageConverter<?> voidContentLengthPreserver() {
        return new MappingJackson2HttpMessageConverter() {
            @Override
            protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException {
                // 针对HEAD请求的Void响应,跳过默认的头清理逻辑
                if (object == null && HttpMethod.HEAD.name().equals(outputMessage.getHeaders().getFirst("Access-Control-Request-Method"))) {
                    return;
                }
                super.writeInternal(object, type, outputMessage);
            }
        };
    }
}

验证方法

发送HEAD请求到目标接口,检查响应头是否包含Content-Length和Last-Modified字段,确认资源存在性与大小信息正常返回。

内容的提问来源于stack exchange,提问作者whistling_marmot

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:52:45