Refactor HTTP Range support with ResourceRegion
Prior to this commit, the `ResourceHttpMessageConverter` would support all HTTP Range requests and `MethodProcessors` would "wrap" controller handler return values with a `HttpRangeResource` to support that use case in Controllers. This commit refactors that support in several ways: * a new ResourceRegion class has been introduced * a new, separate, ResourceRegionHttpMessageConverter handles the HTTP range use cases when serving static resources with the ResourceHttpRequestHandler * the support of HTTP range requests on Controller handlers has been removed until a better solution is found Issue: SPR-14221, SPR-13834
This commit is contained in:
@@ -16,6 +16,10 @@
|
||||
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.springframework.web.servlet.HandlerMapping.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -39,7 +43,6 @@ import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.HttpRangeResource;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.RequestEntity;
|
||||
@@ -53,13 +56,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.context.request.ServletWebRequest;
|
||||
import org.springframework.web.method.support.ModelAndViewContainer;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.BDDMockito.*;
|
||||
import static org.springframework.web.servlet.HandlerMapping.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE;
|
||||
|
||||
/**
|
||||
* Test fixture for {@link HttpEntityMethodProcessor} delegating to a mock
|
||||
* {@link HttpMessageConverter}.
|
||||
@@ -539,39 +535,6 @@ public class HttpEntityMethodProcessorMockTests {
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnTypeResourceByteRange() throws Exception {
|
||||
Resource resource = new ByteArrayResource("Content".getBytes(Charset.forName("UTF-8")));
|
||||
ResponseEntity<Resource> returnValue = ResponseEntity.ok(resource);
|
||||
servletRequest.addHeader("Range", "bytes=0-5");
|
||||
|
||||
given(resourceMessageConverter.canWrite(HttpRangeResource.class, null)).willReturn(true);
|
||||
given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL));
|
||||
given(resourceMessageConverter.canWrite(HttpRangeResource.class, MediaType.APPLICATION_OCTET_STREAM)).willReturn(true);
|
||||
|
||||
processor.handleReturnValue(returnValue, returnTypeResponseEntityResource, mavContainer, webRequest);
|
||||
|
||||
then(resourceMessageConverter).should(times(1)).write(any(ByteArrayResource.class),
|
||||
eq(MediaType.APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class));
|
||||
assertEquals(206, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnTypeResourceIllegalByteRange() throws Exception {
|
||||
Resource resource = new ByteArrayResource("Content".getBytes(Charset.forName("UTF-8")));
|
||||
ResponseEntity<Resource> returnValue = ResponseEntity.ok(resource);
|
||||
servletRequest.addHeader("Range", "illegal");
|
||||
|
||||
given(resourceMessageConverter.canWrite(ByteArrayResource.class, null)).willReturn(true);
|
||||
given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL));
|
||||
|
||||
processor.handleReturnValue(returnValue, returnTypeResponseEntityResource, mavContainer, webRequest);
|
||||
|
||||
then(resourceMessageConverter).should(never()).write(any(ByteArrayResource.class),
|
||||
eq(MediaType.APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class));
|
||||
assertEquals(416, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
private void initStringMessageConversion(MediaType accepted) {
|
||||
given(stringHttpMessageConverter.canWrite(String.class, null)).willReturn(true);
|
||||
given(stringHttpMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN));
|
||||
|
||||
@@ -36,7 +36,6 @@ import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpInputMessage;
|
||||
import org.springframework.http.HttpOutputMessage;
|
||||
import org.springframework.http.HttpRangeResource;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||
@@ -313,37 +312,6 @@ public class RequestResponseBodyMethodProcessorMockTests {
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnTypeResourceByteRange() throws Exception {
|
||||
Resource returnValue = new ByteArrayResource("Content".getBytes(Charset.forName("UTF-8")));
|
||||
servletRequest.addHeader("Range", "bytes=0-5");
|
||||
|
||||
given(resourceMessageConverter.canWrite(HttpRangeResource.class, null)).willReturn(true);
|
||||
given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL));
|
||||
given(resourceMessageConverter.canWrite(HttpRangeResource.class, MediaType.APPLICATION_OCTET_STREAM)).willReturn(true);
|
||||
|
||||
processor.handleReturnValue(returnValue, returnTypeResource, mavContainer, webRequest);
|
||||
|
||||
then(resourceMessageConverter).should(times(1)).write(any(ByteArrayResource.class),
|
||||
eq(MediaType.APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class));
|
||||
assertEquals(206, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void handleReturnTypeResourceIllegalByteRange() throws Exception {
|
||||
Resource returnValue = new ByteArrayResource("Content".getBytes(Charset.forName("UTF-8")));
|
||||
servletRequest.addHeader("Range", "illegal");
|
||||
|
||||
given(resourceMessageConverter.canWrite(ByteArrayResource.class, null)).willReturn(true);
|
||||
given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL));
|
||||
|
||||
processor.handleReturnValue(returnValue, returnTypeResource, mavContainer, webRequest);
|
||||
|
||||
then(resourceMessageConverter).should(never()).write(any(ByteArrayResource.class),
|
||||
eq(MediaType.APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class));
|
||||
assertEquals(416, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
// SPR-9841
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user