Skip to content

Commit f02a2be

Browse files
committed
Allow Resource to add headers for range requests
Closes gh-25976
1 parent 20fe1bc commit f02a2be

File tree

3 files changed

+37
-7
lines changed

3 files changed

+37
-7
lines changed

spring-webflux/src/main/java/org/springframework/web/reactive/resource/ResourceWebHandler.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -352,15 +352,14 @@ public Mono<Void> handle(ServerWebExchange exchange) {
352352

353353
// Check the media type for the resource
354354
MediaType mediaType = MediaTypeFactory.getMediaType(resource).orElse(null);
355+
setHeaders(exchange, resource, mediaType);
355356

356357
// Content phase
357358
if (HttpMethod.HEAD.matches(exchange.getRequest().getMethodValue())) {
358-
setHeaders(exchange, resource, mediaType);
359359
exchange.getResponse().getHeaders().set(HttpHeaders.ACCEPT_RANGES, "bytes");
360360
return Mono.empty();
361361
}
362362

363-
setHeaders(exchange, resource, mediaType);
364363
ResourceHttpMessageWriter writer = getResourceHttpMessageWriter();
365364
Assert.state(writer != null, "No ResourceHttpMessageWriter");
366365
return writer.write(Mono.just(resource),
@@ -535,6 +534,7 @@ protected void setHeaders(ServerWebExchange exchange, Resource resource, @Nullab
535534
if (mediaType != null) {
536535
headers.setContentType(mediaType);
537536
}
537+
538538
if (resource instanceof HttpResource) {
539539
HttpHeaders resourceHeaders = ((HttpResource) resource).getResponseHeaders();
540540
exchange.getResponse().getHeaders().putAll(resourceHeaders);

spring-webmvc/src/main/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -475,22 +475,20 @@ public void handleRequest(HttpServletRequest request, HttpServletResponse respon
475475

476476
// Check the media type for the resource
477477
MediaType mediaType = getMediaType(request, resource);
478+
setHeaders(response, resource, mediaType);
478479

479480
// Content phase
480481
if (METHOD_HEAD.equals(request.getMethod())) {
481-
setHeaders(response, resource, mediaType);
482482
return;
483483
}
484484

485485
ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
486486
if (request.getHeader(HttpHeaders.RANGE) == null) {
487487
Assert.state(this.resourceHttpMessageConverter != null, "Not initialized");
488-
setHeaders(response, resource, mediaType);
489488
this.resourceHttpMessageConverter.write(resource, mediaType, outputMessage);
490489
}
491490
else {
492491
Assert.state(this.resourceRegionHttpMessageConverter != null, "Not initialized");
493-
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
494492
ServletServerHttpRequest inputMessage = new ServletServerHttpRequest(request);
495493
try {
496494
List<HttpRange> httpRanges = inputMessage.getHeaders().getRange();
@@ -499,7 +497,7 @@ public void handleRequest(HttpServletRequest request, HttpServletResponse respon
499497
HttpRange.toResourceRegions(httpRanges, resource), mediaType, outputMessage);
500498
}
501499
catch (IllegalArgumentException ex) {
502-
response.setHeader("Content-Range", "bytes */" + resource.contentLength());
500+
response.setHeader(HttpHeaders.CONTENT_RANGE, "bytes */" + resource.contentLength());
503501
response.sendError(HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
504502
}
505503
}
@@ -694,6 +692,7 @@ protected void setHeaders(HttpServletResponse response, Resource resource, @Null
694692
if (mediaType != null) {
695693
response.setContentType(mediaType.toString());
696694
}
695+
697696
if (resource instanceof HttpResource) {
698697
HttpHeaders resourceHeaders = ((HttpResource) resource).getResponseHeaders();
699698
resourceHeaders.forEach((headerName, headerValues) -> {
@@ -709,6 +708,7 @@ protected void setHeaders(HttpServletResponse response, Resource resource, @Null
709708
}
710709
});
711710
}
711+
712712
response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");
713713
}
714714

spring-webmvc/src/test/java/org/springframework/web/servlet/resource/ResourceHttpRequestHandlerTests.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
import javax.servlet.http.HttpServletResponse;
2626

27+
import org.hamcrest.CoreMatchers;
2728
import org.hamcrest.Matchers;
2829
import org.junit.Before;
2930
import org.junit.Test;
@@ -650,6 +651,35 @@ public void partialContentMultipleByteRanges() throws Exception {
650651
assertEquals("t.", ranges[11]);
651652
}
652653

654+
@Test // gh-25976
655+
public void partialContentByteRangeWithEncodedResource() throws Exception {
656+
String path = "js/foo.js";
657+
EncodedResourceResolverTests.createGzippedFile(path);
658+
659+
ResourceHttpRequestHandler handler = new ResourceHttpRequestHandler();
660+
handler.setResourceResolvers(Arrays.asList(new EncodedResourceResolver(), new PathResourceResolver()));
661+
handler.setLocations(Collections.singletonList(new ClassPathResource("test/", getClass())));
662+
handler.setServletContext(new MockServletContext());
663+
handler.afterPropertiesSet();
664+
665+
this.request.addHeader("Accept-Encoding", "gzip");
666+
this.request.addHeader("Range", "bytes=0-1");
667+
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, path);
668+
handler.handleRequest(this.request, this.response);
669+
670+
assertEquals(206, this.response.getStatus());
671+
assertThat(response.getHeaderNames(), CoreMatchers.hasItems(
672+
"Last-Modified", "Content-Length", "Content-Type", "Content-Encoding",
673+
"Vary", "Accept-Ranges", "Content-Range"));
674+
675+
assertEquals("application/javascript", this.response.getContentType());
676+
assertEquals(2, this.response.getContentLength());
677+
assertEquals("bytes 0-1/66", this.response.getHeader("Content-Range"));
678+
assertEquals("bytes", this.response.getHeaderValue("Accept-Ranges"));
679+
assertEquals("gzip", this.response.getHeaderValue("Content-Encoding"));
680+
assertEquals("Accept-Encoding", this.response.getHeaderValue("Vary"));
681+
}
682+
653683
@Test // SPR-14005
654684
public void doOverwriteExistingCacheControlHeaders() throws Exception {
655685
this.request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, "foo.css");

0 commit comments

Comments
 (0)