/* * Copyright (c) 2009. The Codehaus. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.codehaus.httpcache4j; import java.io.File; import org.codehaus.httpcache4j.payload.StringPayload; import org.codehaus.httpcache4j.resolver.ResponseResolver; import org.codehaus.httpcache4j.util.TestUtil; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.webapp.WebAppContext; import org.junit.AfterClass; import org.codehaus.httpcache4j.cache.CacheStorage; import org.codehaus.httpcache4j.cache.HTTPCache; import org.codehaus.httpcache4j.payload.FilePayload; import org.codehaus.httpcache4j.payload.ByteArrayPayload; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import java.io.FileInputStream; import java.net.URI; import java.time.LocalDateTime; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.servlet.ServletContextHandler; import static org.junit.Assert.*; /** * @author <a href="mailto:hamnis@codehaus.org">Erlend Hamnaberg</a> * @version $Revision: $ */ public abstract class AbstractCacheIntegrationTest { private static URI baseRequestURI; private static URI baseCustomRequestURI; private static final String TEST_FILE = "testFile"; private HTTPCache cache; private CacheStorage storage; private static Server jettyServer; @BeforeClass public static void setupServer() throws Exception { baseRequestURI = URI.create(String.format("http://localhost:%s/testbed/", JettyServer.PORT)); baseCustomRequestURI = URI.create(String.format("http://localhost:%s/custom/", JettyServer.PORT)); System.out.println("::: Starting server :::"); jettyServer = new Server(JettyServer.PORT); final String webapp = "target/testbed/"; if (!TestUtil.getTestFile(webapp).exists()) { throw new IllegalStateException("WebApp dir does not exist!"); } HandlerList handlerList = new HandlerList(); Handler webAppHandler = new WebAppContext(webapp, "/testbed"); handlerList.addHandler(webAppHandler); ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS); contextHandler.setContextPath("/custom"); contextHandler.addServlet(VaryResourceServlet.class, "/*"); handlerList.addHandler(contextHandler); jettyServer.setHandler(handlerList); jettyServer.start(); } @AfterClass public static void shutdownServer() throws Exception { System.out.println("::: Stopping server :::"); jettyServer.stop(); } @Before public void before() { storage = createStorage(); cache = new HTTPCache(storage, createReponseResolver()); HTTPRequest req = new HTTPRequest(baseRequestURI.resolve(TEST_FILE), HTTPMethod.PUT); req = req.payload(new FilePayload(new File("pom.xml"), MIMEType.valueOf("application/xml"))); cache.execute(req); } protected abstract ResponseResolver createReponseResolver(); protected abstract CacheStorage createStorage(); @Test public void POSTWithContentLength() { HTTPRequest req = new HTTPRequest(baseCustomRequestURI, HTTPMethod.POST).addHeader(HeaderConstants.CONTENT_LENGTH, "1000"); req = req.payload(new StringPayload("test", MIMEType.valueOf("text/plain"))); HTTPResponse response = cache.execute(req); assertEquals(Status.OK, response.getStatus()); } @Test public void GETNotCacheableResponse() { HTTPResponse response = get(baseRequestURI.resolve(TEST_FILE)); assertNull(response.getHeaders().getETag().orElse(null)); assertNull(response.getHeaders().getLastModified().orElse(null)); assertEquals(Status.OK, response.getStatus()); assertEquals(0, storage.size()); assertEquals(CacheHeaderBuilder.getBuilder().createMISSXCacheHeader(), response.getHeaders().getFirstHeader(HeaderConstants.X_CACHE).get()); } @Test public void GETWithETagResponse() { HTTPResponse response = get(baseRequestURI.resolve(String.format("etag/%s", TEST_FILE))); assertNotNull(response.getHeaders().getETag().orElse(null)); assertNull(response.getHeaders().getLastModified().orElse(null)); assertEquals(Status.OK, response.getStatus()); assertEquals(1, storage.size()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); } @Test public void GETWithETagThenPUTAndReGETResponse() { URI uri = baseRequestURI.resolve(String.format("etag/%s", TEST_FILE)); HTTPResponse response = get(uri); assertNotNull(response.getHeaders().getETag().orElse(null)); assertNull(response.getHeaders().getLastModified().orElse(null)); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE).orElse(null)); assertEquals(1, storage.size()); response = cache.execute(new HTTPRequest(uri, HTTPMethod.PUT).withPayload(new StringPayload("test", MIMEType.valueOf("text/plain")))); assertEquals(0, storage.size()); assertEquals(Status.NO_CONTENT, response.getStatus()); assertNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE).orElse(null)); response = get(uri); assertNotNull(response.getHeaders().getETag().orElse(null)); assertNull(response.getHeaders().getLastModified().orElse(null)); assertEquals(Status.OK, response.getStatus()); assertEquals(1, storage.size()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); } @Test public void GETWithBasicAuthentication() { URI uri = baseRequestURI.resolve(String.format("etag/basic,u=u,p=p/%s", TEST_FILE)); HTTPResponse response = get(uri); assertEquals(Status.UNAUTHORIZED, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); response.consume(); HTTPRequest request = new HTTPRequest(uri).withChallenge(new UsernamePasswordChallenge("u", "p")); response = cache.execute(request); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); response.consume(); } @Test public void PUTWithBasicAuthentication() throws Exception { URI uri = baseRequestURI.resolve(String.format("etag/basic,u=u,p=p/%s", TEST_FILE)); HTTPResponse response = doRequest(uri, HTTPMethod.PUT); assertEquals(Status.UNAUTHORIZED, response.getStatus()); response.consume(); HTTPRequest request = new HTTPRequest(uri, HTTPMethod.PUT).withPayload(new StringPayload("test", MIMEType.valueOf("text/plain"))).withChallenge(new UsernamePasswordChallenge("u", "p")) .withPayload(new ByteArrayPayload(new FileInputStream(new File("pom.xml")), MIMEType.valueOf("application/xml"))); response = cache.execute(request); assertEquals(Status.NO_CONTENT, response.getStatus()); response.consume(); } @Test public void GETWithDigestAuthentication() { URI uri = baseRequestURI.resolve(String.format("etag/digest,u=u,p=p/%s", TEST_FILE)); HTTPResponse response = get(uri); assertEquals(Status.UNAUTHORIZED, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); response.consume(); HTTPRequest request = new HTTPRequest(uri).challenge(new UsernamePasswordChallenge("u", "p")); response = cache.execute(request); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); response.consume(); } @Test public void GETWithLastModified() { URI uri = baseRequestURI.resolve(String.format("lm/%s", TEST_FILE)); HTTPResponse response = get(uri); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertFalse(response.isCached()); response.consume(); response = get(uri); assertEquals(Status.OK, response.getStatus()); assertTrue(response.isCached()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); response.consume(); } @Test public void GETWithLastModifiedAndETag() { URI uri = baseRequestURI.resolve(String.format("lm/etag/%s", TEST_FILE)); HTTPResponse response = get(uri); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertFalse(response.isCached()); response.consume(); response = get(uri); assertEquals(Status.OK, response.getStatus()); assertTrue(response.isCached()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); response.consume(); } @Test public void GETWithVaryForAccept() { HTTPRequest request = new HTTPRequest(baseCustomRequestURI, HTTPMethod.GET).addHeader(HeaderConstants.ACCEPT, "text/plain"); HTTPResponse response = cache.execute(request); assertEquals(Status.OK, response.getStatus()); assertTrue(MIMEType.valueOf("text/plain").includes(response.getPayload().get().getMimeType())); assertFalse(response.isCached()); response.consume(); response = cache.execute(request); assertTrue(MIMEType.valueOf("text/plain").includes(response.getPayload().get().getMimeType())); assertTrue(response.isCached()); response.consume(); request = new HTTPRequest(baseCustomRequestURI, HTTPMethod.GET).addHeader(HeaderConstants.ACCEPT, "text/xml"); response = cache.execute(request); response.consume(); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertFalse(response.isCached()); assertTrue(MIMEType.valueOf("text/xml").includes(response.getPayload().get().getMimeType())); response = cache.execute(request); response.consume(); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertTrue(response.isCached()); assertTrue(MIMEType.valueOf("text/xml").includes(response.getPayload().get().getMimeType())); assertEquals(2, storage.size()); } /** * Tests that requests come from the cache, but that the * response isn't specified that the cache is used when the response * is generated from the server */ @Test public void GETWithMaxAge() { URI uri = baseRequestURI.resolve(String.format("cc,10/%s", TEST_FILE)); HTTPResponse response = get(uri); // System.out.println(response.getHeaders()); assertEquals(Status.OK, response.getStatus()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); LocalDateTime originalDate = response.getHeaders().getDate().orElse(null); assertTrue(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE).get().contains("MISS")); assertFalse(response.isCached()); response.consume(); try { Thread.sleep(5000); } catch (Exception e) {} response = get(uri); LocalDateTime cacheDate = response.getHeaders().getDate().orElse(null); assertEquals(Status.OK, response.getStatus()); assertTrue(originalDate.equals(cacheDate)); assertTrue(response.isCached()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertTrue(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE).get().contains("HIT")); response.consume(); // sleep here. The response should come from the server try { Thread.sleep(12000); } catch (Exception e) {} response = get(uri); LocalDateTime nonCacheDate = response.getHeaders().getDate().orElse(null); assertEquals(Status.OK, response.getStatus()); assertFalse(originalDate.equals(nonCacheDate)); assertFalse(response.isCached()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertTrue(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE).get().contains("MISS")); response.consume(); try { Thread.sleep(2000); } catch (Exception e) {} response = get(uri); LocalDateTime shouldBeAboveNonCacheDate = response.getHeaders().getDate().orElse(null); assertEquals(Status.OK, response.getStatus()); assertTrue(nonCacheDate.equals(shouldBeAboveNonCacheDate)); assertTrue(response.isCached()); assertNotNull(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE)); assertTrue(response.getHeaders().getFirstHeaderValue(HeaderConstants.X_CACHE).get().contains("HIT")); response.consume(); } private HTTPResponse get(URI uri) { return doRequest(uri, HTTPMethod.GET); } private HTTPResponse doRequest(URI uri, HTTPMethod method) { HTTPRequest request = new HTTPRequest(uri, method); if (method.canHavePayload()) { request = request.withPayload(new StringPayload("test", MIMEType.valueOf("text/plain"))); } HTTPResponse response = cache.execute(request); assertNotNull(response); assertFalse(response.getStatus().equals(Status.INTERNAL_SERVER_ERROR)); return response; } }