package org.jboss.resteasy.test.cache; import static org.jboss.resteasy.test.TestPortProvider.generateURL; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.ws.rs.Consumes; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation.Builder; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import org.jboss.resteasy.annotations.cache.Cache; import org.jboss.resteasy.plugins.cache.server.ServerCacheFeature; import org.jboss.resteasy.plugins.server.netty.NettyJaxrsServer; import org.jboss.resteasy.spi.Registry; import org.jboss.resteasy.spi.ResteasyDeployment; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.test.TestPortProvider; import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @version $Revision: 1 $ */ public class ServerCacheTest { private static NettyJaxrsServer server; private static ResteasyDeployment deployment; private static int count = 0; private static int plainCount = 0; private static int htmlCount = 0; private static Client client; @BeforeClass public static void beforeClass() throws Exception { server = new NettyJaxrsServer(); server.setPort(TestPortProvider.getPort()); server.setRootResourcePath("/"); server.start(); deployment = server.getDeployment(); client = ClientBuilder.newClient(); } @AfterClass public static void afterClass() throws Exception { server.stop(); server = null; deployment = null; client.close(); } public Registry getRegistry() { return deployment.getRegistry(); } public ResteasyProviderFactory getProviderFactory() { return deployment.getProviderFactory(); } /** * @param resource */ public static void addPerRequestResource(Class<?> resource) { deployment.getRegistry().addPerRequestResource(resource); } public String readString(InputStream in) throws IOException { char[] buffer = new char[1024]; StringBuilder builder = new StringBuilder(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); int wasRead = 0; do { wasRead = reader.read(buffer, 0, 1024); if (wasRead > 0) { builder.append(buffer, 0, wasRead); } } while (wasRead > -1); return builder.toString(); } @Path("/cache") public static class MyService { @GET @Produces("text/plain") @Cache(maxAge = 2) public String get() { count++; return "hello world" + count; } @PUT @Consumes("text/plain") public void put(String val) { } @GET @Produces("text/plain") @Path("accepts") @Cache(maxAge = 2) public String getPlain() { plainCount++; return "plain" + plainCount; } @GET @Produces("text/html") @Path("accepts") @Cache(maxAge = 2) public String getHtml() { htmlCount++; return "html" + htmlCount; } @GET @Produces("text/plain") @Path("stuff") @Cache(maxAge = 2) public String getStuff() { count++; return "stuff"; } @GET @Produces("text/plain") @Path("vary") @Cache(maxAge = 2) public Response getVary(@HeaderParam("X-Test-Vary") @DefaultValue("default") String testVary) { count++; return Response.ok(testVary).header(HttpHeaders.VARY, "X-Test-Vary").header("X-Count", count).build(); } } @Path("/cache") public static interface MyProxy { @GET @Produces("text/plain") public String get(); } @Before public void setUp() throws Exception { getProviderFactory().register(ServerCacheFeature.class); addPerRequestResource(MyService.class); } @Test public void testNoCacheHitValidation() throws Exception { // test that after a cache expiration NOT MODIFIED is still returned if matching etags count = 0; String etag = null; { Builder request = client.target(generateURL("/cache/stuff")).request(); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "stuff"); } Thread.sleep(2000); { Builder request = client.target(generateURL("/cache/stuff")).request(); request.header(HttpHeaders.IF_NONE_MATCH, etag); Response response = request.get(); Assert.assertEquals(Response.Status.NOT_MODIFIED.getStatusCode(), response.getStatus()); Assert.assertEquals(2, count); response.close(); } } @Test public void testCache() throws Exception { count = 0; String etag = null; { Builder request = client.target(generateURL("/cache")).request(); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "hello world" + 1); } { Builder request = client.target(generateURL("/cache")).request(); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "hello world" + 1); } // test if-not-match { Builder request = client.target(generateURL("/cache")).request(); request.header(HttpHeaders.IF_NONE_MATCH, etag); Response response = request.get(); Assert.assertEquals(Response.Status.NOT_MODIFIED.getStatusCode(), response.getStatus()); response.close(); } Thread.sleep(2000); { Builder request = client.target(generateURL("/cache")).request(); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "hello world" + 2); } { Builder request = client.target(generateURL("/cache")).request(); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "hello world" + 2); } { Builder request = client.target(generateURL("/cache")).request(); Response response = request.put(Entity.entity("yo", "text/plain")); Assert.assertEquals(204, response.getStatus()); response.close(); } { Builder request = client.target(generateURL("/cache")).request(); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "hello world" + 3); } } @Test public void testAccepts() throws Exception { count = 0; plainCount = 0; htmlCount = 0; String etag = null; { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/plain").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "plain" + 1); } { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/plain").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "plain" + 1); } { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/html").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "html" + 1); } { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/html").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "html" + 1); } } @Test public void testPreferredAccepts() throws Exception { count = 0; plainCount = 0; htmlCount = 0; String etag = null; { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/plain").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "plain" + 1); } { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/html").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "html" + 1); } { Builder request = client.target(generateURL("/cache/accepts")).request(); request.header(HttpHeaders.ACCEPT, "text/html;q=0.5, text/plain"); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "plain" + 1); } { Builder request = client.target(generateURL("/cache/accepts")).request(); request.header(HttpHeaders.ACCEPT, "text/plain;q=0.5, text/html"); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "html" + 1); } } @Test public void testPreferredButNotCachedAccepts() throws Exception { count = 0; plainCount = 0; htmlCount = 0; String etag = null; { Builder request = client.target(generateURL("/cache/accepts")).request(); Response response = request.accept("text/plain").get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "plain" + 1); } // we test that the preferred can be handled { Builder request = client.target(generateURL("/cache/accepts")).request(); request.header(HttpHeaders.ACCEPT, "text/plain;q=0.5, text/html"); Response response = request.get(); Assert.assertEquals(200, response.getStatus()); String cc = response.getHeaderString(HttpHeaders.CACHE_CONTROL); Assert.assertNotNull(cc); etag = response.getHeaderString(HttpHeaders.ETAG); Assert.assertNotNull(etag); Assert.assertEquals(response.readEntity(String.class), "html" + 1); } } @Test public void testVary() throws Exception { int cachedCount; { Builder request = client.target(generateURL("/cache/vary")).request(); Response foo = request.accept("text/plain").header("X-Test-Vary", "foo").get(); Assert.assertEquals("foo", foo.readEntity(String.class)); cachedCount = Integer.parseInt(foo.getHeaderString("X-Count")); } { Builder request = client.target(generateURL("/cache/vary")).request(); Response bar = request.accept("text/plain").header("X-Test-Vary", "bar").get(); Assert.assertEquals("bar", bar.readEntity(String.class)); } { Builder request = client.target(generateURL("/cache/vary")).request(); Response foo = request.accept("text/plain").header("X-Test-Vary", "foo").get(); Assert.assertEquals("foo", foo.readEntity(String.class)); int currentCount = Integer.parseInt(foo.getHeaderString("X-Count")); Assert.assertEquals(cachedCount, currentCount); } } @Test public void testProxy() throws Exception { /* MyProxy proxy = ProxyFactory.create(MyProxy.class, generateBaseUrl()); CacheFactory.makeCacheable(proxy); String rtn = null; rtn = proxy.get(); Assert.assertEquals("hello world" + 1, rtn); Assert.assertEquals(1, count); rtn = proxy.get(); Assert.assertEquals("hello world" + 1, rtn); Assert.assertEquals(1, count); Thread.sleep(2000); rtn = proxy.get(); Assert.assertEquals("hello world" + 2, rtn); Assert.assertEquals(2, count); rtn = proxy.get(); Assert.assertEquals("hello world" + 2, rtn); Assert.assertEquals(2, count); */ } }