Disable HTTP Range support for InputStreamResource
Prior to this commit, the `AbstractMessageConverterMethodProcessor`
would fail to convert `InputStreamResource` to `ResourceRegion` as
expected, since the content length cannot be read without consuming the
stream. This is enforced by the `HttpRange` class.
Now the method processor would still try to output HTTP range response
headers to provide range support information. This step is using the
resource content length and reads the input stream, leading to
exceptions such as "IllegalStateException: InputStream has already been
read".
This commit improves the return type detection and excludes early
`InputStreamResource` return types. With those types, HTTP range support
is now completely disabled.
Issue: SPR-16754
(cherry picked from commit e9a8a5065b)
This commit is contained in:
parent
4ff595e2bc
commit
72cfe41f30
|
|
@ -31,6 +31,7 @@ import javax.servlet.http.HttpServletResponse;
|
|||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourceRegion;
|
||||
import org.springframework.http.HttpEntity;
|
||||
|
|
@ -302,7 +303,8 @@ public abstract class AbstractMessageConverterMethodProcessor extends AbstractMe
|
|||
* Return whether the returned value or the declared return type extend {@link Resource}
|
||||
*/
|
||||
protected boolean isResourceType(@Nullable Object value, MethodParameter returnType) {
|
||||
return Resource.class.isAssignableFrom(value != null ? value.getClass() : returnType.getParameterType());
|
||||
Class<?> clazz = getReturnValueType(value, returnType);
|
||||
return clazz != InputStreamResource.class && Resource.class.isAssignableFrom(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -16,7 +16,9 @@
|
|||
|
||||
package org.springframework.web.servlet.mvc.method.annotation;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
|
@ -27,6 +29,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
|
@ -35,6 +38,7 @@ import org.mockito.ArgumentCaptor;
|
|||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
|
|
@ -547,6 +551,23 @@ public class HttpEntityMethodProcessorMockTests {
|
|||
assertEquals(416, servletResponse.getStatus());
|
||||
}
|
||||
|
||||
@Test //SPR-16754
|
||||
public void disableRangeSupportForStreamingResponses() throws Exception {
|
||||
InputStream is = new ByteArrayInputStream("Content".getBytes(StandardCharsets.UTF_8));
|
||||
InputStreamResource resource = new InputStreamResource(is, "test");
|
||||
ResponseEntity<Resource> returnValue = ResponseEntity.ok(resource);
|
||||
servletRequest.addHeader("Range", "bytes=0-5");
|
||||
|
||||
given(resourceMessageConverter.canWrite(any(), eq(null))).willReturn(true);
|
||||
given(resourceMessageConverter.canWrite(any(), eq(APPLICATION_OCTET_STREAM))).willReturn(true);
|
||||
|
||||
processor.handleReturnValue(returnValue, returnTypeResponseEntityResource, mavContainer, webRequest);
|
||||
then(resourceMessageConverter).should(times(1)).write(
|
||||
any(InputStreamResource.class), eq(APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class));
|
||||
assertEquals(200, servletResponse.getStatus());
|
||||
assertThat(servletResponse.getHeader(HttpHeaders.ACCEPT_RANGES), Matchers.isEmptyOrNullString());
|
||||
}
|
||||
|
||||
@Test //SPR-14767
|
||||
public void shouldHandleValidatorHeadersInPutResponses() throws Exception {
|
||||
servletRequest.setMethod("PUT");
|
||||
|
|
|
|||
Loading…
Reference in New Issue