diff --git a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayFilter.java b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayFilter.java index 181888977..1585aa696 100644 --- a/gateway-server/src/main/java/org/apache/knox/gateway/GatewayFilter.java +++ b/gateway-server/src/main/java/org/apache/knox/gateway/GatewayFilter.java @@ -39,6 +39,7 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpHeaders; import org.apache.knox.gateway.audit.api.Action; import org.apache.knox.gateway.audit.api.ActionOutcome; import org.apache.knox.gateway.audit.api.AuditContext; @@ -78,6 +79,10 @@ public void doFilter(ServletRequest servletRequest, ServletResponse servletRespo AuditConstants.DEFAULT_AUDITOR_NAME, AuditConstants.KNOX_SERVICE_NAME, AuditConstants.KNOX_COMPONENT_NAME ); + private static final String CACHE_CONTROL_HEADER_VALUE = "no-cache, no-store, must-revalidate"; + private static final String PRAGMA_HEADER_VALUE = "no-cache"; + private static final String EXPIRES_HEADER_VALUE = "0"; + private Set holders; private Matcher chains; private FilterConfig config; @@ -203,6 +208,10 @@ public void doFilter( ServletRequest servletRequest, ServletResponse servletResp httpResponse.setStatus( HttpServletResponse.SC_NOT_FOUND ); } + if("/".equals(requestPath)) { + this.addCacheHeaders(httpResponse); + } + //KAM[ Don't do this or the Jetty default servlet will overwrite any response setup by the filter. // filterChain.doFilter( servletRequest, servletResponse ); //] @@ -271,6 +280,12 @@ private void auditLog(ServletRequest servletRequest, ServletResponse servletResp auditor.audit(Action.ACCESS, requestUri, ResourceType.URI, actionOutcome, RES.responseStatus(status)); } + private void addCacheHeaders(HttpServletResponse httpResponse) { + httpResponse.addHeader(HttpHeaders.CACHE_CONTROL, GatewayFilter.CACHE_CONTROL_HEADER_VALUE); + httpResponse.addHeader(HttpHeaders.PRAGMA, GatewayFilter.PRAGMA_HEADER_VALUE); + httpResponse.addHeader(HttpHeaders.EXPIRES, GatewayFilter.EXPIRES_HEADER_VALUE); + } + private class Chain implements FilterChain { private List chainList; private String resourceRole; diff --git a/gateway-server/src/test/java/org/apache/knox/gateway/GatewayFilterTest.java b/gateway-server/src/test/java/org/apache/knox/gateway/GatewayFilterTest.java index 32cbb0625..4dadbd969 100644 --- a/gateway-server/src/test/java/org/apache/knox/gateway/GatewayFilterTest.java +++ b/gateway-server/src/test/java/org/apache/knox/gateway/GatewayFilterTest.java @@ -291,4 +291,72 @@ public void testDefaultServicePathTopologyRequestAttribute() throws Exception { assertThat(filter.url, is("http://host:8443/gateway/sandbox/test-role/test-path/test-resource")); } + + @Test + public void testCacheHeaders() throws ServletException, IOException { + FilterConfig config = EasyMock.createNiceMock(FilterConfig.class); + EasyMock.replay(config); + + HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); + ServletContext context = EasyMock.createNiceMock(ServletContext.class); + GatewayConfig gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.expect(request.getPathInfo()).andReturn(null).anyTimes(); + EasyMock.expect(request.getServletPath()).andReturn("/").anyTimes(); + EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes(); + EasyMock.expect(context.getAttribute( + GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes(); + EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn( + "Custom-Forwarded-For").anyTimes(); + EasyMock.replay(request); + EasyMock.replay(context); + EasyMock.replay(gatewayConfig); + + HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class); + response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + response.addHeader("Pragma", "no-cache"); + response.addHeader("Expires", "0"); + EasyMock.replay(response); + + FilterChain chain = EasyMock.createNiceMock(FilterChain.class); + EasyMock.replay(chain); + + GatewayFilter gateway = new GatewayFilter(); + gateway.init(config); + gateway.doFilter(request, response, chain); + gateway.destroy(); + + EasyMock.verify(response); + } + + @Test + public void testCacheHeadersNotCalled() throws ServletException, IOException { + FilterConfig config = EasyMock.createNiceMock(FilterConfig.class); + EasyMock.replay(config); + + HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class); + ServletContext context = EasyMock.createNiceMock(ServletContext.class); + GatewayConfig gatewayConfig = EasyMock.createNiceMock(GatewayConfig.class); + EasyMock.expect(request.getPathInfo()).andReturn("/test/path").anyTimes(); + EasyMock.expect(request.getServletContext()).andReturn(context).anyTimes(); + EasyMock.expect(context.getAttribute( + GatewayConfig.GATEWAY_CONFIG_ATTRIBUTE)).andReturn(gatewayConfig).anyTimes(); + EasyMock.expect(gatewayConfig.getHeaderNameForRemoteAddress()).andReturn( + "Custom-Forwarded-For").anyTimes(); + EasyMock.replay(request); + EasyMock.replay(context); + EasyMock.replay(gatewayConfig); + + HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class); + response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate"); + EasyMock.expectLastCall().andThrow(new AssertionError("Cache-Control add header was called")); + EasyMock.replay(response); + + FilterChain chain = EasyMock.createNiceMock(FilterChain.class); + EasyMock.replay(chain); + + GatewayFilter gateway = new GatewayFilter(); + gateway.init(config); + gateway.doFilter(request, response, chain); + gateway.destroy(); + } }