Restrict ETag generation in ShallowEtagHeaderFilter
Prior to this commit, all 2xx HTTP responses were eligible for ETag generation in ShallowEtagHeaderFilter. In some cases, this would use CPU resources for no reason since HTTP clients would not use ETags. This commit is an optimization and restricts ETags generation in cases where (all conditions must be met): - response has a 2xx status - request is a GET - response does not contain "no-store" in its "Cache-Control" header Issue: SPR-11110
This commit is contained in:
parent
d550ffb37f
commit
6fba8292f5
|
|
@ -28,6 +28,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpServletResponseWrapper;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
|
@ -51,6 +52,10 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
|||
|
||||
private static final String HEADER_IF_NONE_MATCH = "If-None-Match";
|
||||
|
||||
private static final String HEADER_CACHE_CONTROL = "Cache-Control";
|
||||
|
||||
private static final String DIRECTIVE_NO_STORE = "no-store";
|
||||
|
||||
|
||||
/**
|
||||
* The default value is "false" so that the filter may delay the generation of
|
||||
|
|
@ -122,7 +127,13 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
|||
|
||||
/**
|
||||
* Indicates whether the given request and response are eligible for ETag generation.
|
||||
* <p>The default implementation returns {@code true} for response status codes in the {@code 2xx} series.
|
||||
* <p>The default implementation returns {@code true} if all conditions match:
|
||||
* <ul>
|
||||
* <li>response status codes in the {@code 2xx} series</li>
|
||||
* <li>request method is a GET</li>
|
||||
* <li>response Cache-Control header is null or does not contain a "no-store" directive</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @param response the HTTP response
|
||||
* @param responseStatusCode the HTTP response status code
|
||||
|
|
@ -132,7 +143,10 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
|||
protected boolean isEligibleForEtag(HttpServletRequest request, HttpServletResponse response,
|
||||
int responseStatusCode, byte[] responseBody) {
|
||||
|
||||
return (responseStatusCode >= 200 && responseStatusCode < 300);
|
||||
return (responseStatusCode >= 200 && responseStatusCode < 300)
|
||||
&& HttpMethod.GET.name().equals(request.getMethod())
|
||||
&& (response.getHeader(HEADER_CACHE_CONTROL) == null
|
||||
|| !response.getHeader(HEADER_CACHE_CONTROL).contains(DIRECTIVE_NO_STORE));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -48,6 +48,13 @@ public class ShallowEtagHeaderFilterTests {
|
|||
|
||||
assertTrue(filter.isEligibleForEtag(request, response, 200, new byte[0]));
|
||||
assertFalse(filter.isEligibleForEtag(request, response, 300, new byte[0]));
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels");
|
||||
assertFalse(filter.isEligibleForEtag(request, response, 200, new byte[0]));
|
||||
|
||||
request = new MockHttpServletRequest("POST", "/hotels");
|
||||
request.addHeader("Cache-Control","must-revalidate, no-store");
|
||||
assertFalse(filter.isEligibleForEtag(request, response, 200, new byte[0]));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue