From 9adfa5e8b0f0cd65a0b14740e0a0f9832d80edcb Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 7 Apr 2022 13:51:21 +0200 Subject: [PATCH] Add HEAD support in MVC/WebFlux Resource handling This commit introduces explicit HEAD support in Spring MVC's ResourceHttpRequestHandler and WebFlux's ResourceWebHandler, adding just headers but no body. Closes gh-28291 --- .../http/codec/ResourceHttpMessageWriter.java | 33 ++++++++++++------- .../ResourceHttpMessageConverter.java | 8 +++++ .../reactive/resource/ResourceWebHandler.java | 15 ++++++--- .../resource/ResourceWebHandlerTests.java | 5 ++- .../resource/ResourceHttpRequestHandler.java | 9 ++++- .../ResourceHttpRequestHandlerTests.java | 3 +- 6 files changed, 54 insertions(+), 19 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java index af456989e0..5765fe218c 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java @@ -116,8 +116,27 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter { private Mono writeResource(Resource resource, ResolvableType type, @Nullable MediaType mediaType, ReactiveHttpOutputMessage message, Map hints) { + addHeaders(message, resource, mediaType, hints); + + return zeroCopy(resource, null, message, hints) + .orElseGet(() -> { + Mono input = Mono.just(resource); + DataBufferFactory factory = message.bufferFactory(); + Flux body = this.encoder.encode(input, factory, type, message.getHeaders().getContentType(), hints); + if (logger.isDebugEnabled()) { + body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger)); + } + return message.writeWith(body); + }); + } + + /** + * Adds the default headers for the given resource to the given message. + * @since 6.0 + */ + public void addHeaders(ReactiveHttpOutputMessage message, Resource resource, @Nullable MediaType contentType, Map hints) { HttpHeaders headers = message.getHeaders(); - MediaType resourceMediaType = getResourceMediaType(mediaType, resource, hints); + MediaType resourceMediaType = getResourceMediaType(contentType, resource, hints); headers.setContentType(resourceMediaType); if (headers.getContentLength() < 0) { @@ -126,17 +145,7 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter { headers.setContentLength(length); } } - - return zeroCopy(resource, null, message, hints) - .orElseGet(() -> { - Mono input = Mono.just(resource); - DataBufferFactory factory = message.bufferFactory(); - Flux body = this.encoder.encode(input, factory, type, resourceMediaType, hints); - if (logger.isDebugEnabled()) { - body = body.doOnNext(buffer -> Hints.touchDataBuffer(buffer, hints, logger)); - } - return message.writeWith(body); - }); + headers.set(HttpHeaders.ACCEPT_RANGES, "bytes"); } private static MediaType getResourceMediaType( diff --git a/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java index 17aa290ca9..e49bdd2551 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/ResourceHttpMessageConverter.java @@ -122,6 +122,14 @@ public class ResourceHttpMessageConverter extends AbstractHttpMessageConverter