Disable ShallowEtagHeaderFilter for HTTP streaming

Issue: SPR-12960
This commit is contained in:
Rossen Stoyanchev
2015-05-03 10:24:14 +02:00
parent 68ecb92d1f
commit 49e90575e9
6 changed files with 127 additions and 61 deletions

View File

@@ -18,8 +18,12 @@ package org.springframework.web.filter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -55,11 +59,12 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
private static final String DIRECTIVE_NO_STORE = "no-store";
/** Checking for Servlet 3.0+ HttpServletResponse.getHeader(String) */
private static final boolean responseGetHeaderAvailable =
ClassUtils.hasMethod(HttpServletResponse.class, "getHeader", String.class);
private static final String STREAMING_ATTRIBUTE = ShallowEtagHeaderFilter.class.getName() + ".STREAMING";
/**
* The default value is "false" so that the filter may delay the generation of
@@ -76,12 +81,12 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
HttpServletResponse responseToUse = response;
if (!isAsyncDispatch(request) && !(response instanceof ContentCachingResponseWrapper)) {
responseToUse = new ContentCachingResponseWrapper(response);
responseToUse = new HttpStreamingAwareContentCachingResponseWrapper(response, request);
}
filterChain.doFilter(request, responseToUse);
if (!isAsyncStarted(request)) {
if (!isAsyncStarted(request) && !isContentCachingDisabled(request)) {
updateResponse(request, responseToUse);
}
}
@@ -90,7 +95,6 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
ContentCachingResponseWrapper responseWrapper =
WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
Assert.notNull(responseWrapper, "ShallowEtagResponseWrapper not found");
HttpServletResponse rawResponse = (HttpServletResponse) responseWrapper.getResponse();
int statusCode = responseWrapper.getStatusCode();
@@ -169,4 +173,48 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
return builder.toString();
}
/**
* This method can be used to disable the content caching response wrapper
* of the ShallowEtagHeaderFilter. This can be done before the start of HTTP
* streaming for example where the response will be written to asynchronously
* and not in the context of a Servlet container thread.
* @since 4.2
*/
public static void disableContentCaching(ServletRequest request) {
Assert.notNull(request);
request.setAttribute(STREAMING_ATTRIBUTE, true);
}
private static boolean isContentCachingDisabled(HttpServletRequest request) {
return (request.getAttribute(STREAMING_ATTRIBUTE) != null);
}
private static class HttpStreamingAwareContentCachingResponseWrapper extends ContentCachingResponseWrapper {
private final HttpServletRequest request;
public HttpStreamingAwareContentCachingResponseWrapper(HttpServletResponse response,
HttpServletRequest request) {
super(response);
this.request = request;
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
return (useRawResponse() ? getResponse().getOutputStream() : super.getOutputStream());
}
@Override
public PrintWriter getWriter() throws IOException {
return (useRawResponse() ? getResponse().getWriter() : super.getWriter());
}
private boolean useRawResponse() {
return isContentCachingDisabled(this.request);
}
}
}

View File

@@ -91,7 +91,7 @@ public class ContentCachingResponseWrapper extends HttpServletResponseWrapper {
}
@Override
public ServletOutputStream getOutputStream() {
public ServletOutputStream getOutputStream() throws IOException {
return this.outputStream;
}