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
相关产品推荐
相关产品推荐

