@Test public void testClientExcludedHosts() throws Exception { prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); } }); int port = serverConnector.getLocalPort(); client .getProxyConfiguration() .getProxies() .get(0) .getExcludedAddresses() .add("127.0.0.1:" + port); // Try with a proxied host ContentResponse response = client.newRequest("localhost", port).timeout(5, TimeUnit.SECONDS).send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); // Try again with an excluded host response = client.newRequest("127.0.0.1", port).timeout(5, TimeUnit.SECONDS).send(); Assert.assertEquals(200, response.getStatus()); Assert.assertFalse(response.getHeaders().containsKey(PROXIED_HEADER)); }
/** @throws Exception */ public void testSessionRenewal() throws Exception { String contextPath = ""; String servletMapping = "/server"; int maxInactive = 1; int scavengePeriod = 3; _server = createServer(0, maxInactive, scavengePeriod, SessionCache.NEVER_EVICT); WebAppContext context = _server.addWebAppContext(".", contextPath); context.setParentLoaderPriority(true); context.addServlet(TestServlet.class, servletMapping); TestHttpSessionIdListener testListener = new TestHttpSessionIdListener(); context.addEventListener(testListener); HttpClient client = new HttpClient(); try { _server.start(); int port = _server.getPort(); client.start(); // make a request to create a session ContentResponse response = client.GET("http://localhost:" + port + contextPath + servletMapping + "?action=create"); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); String sessionCookie = response.getHeaders().get("Set-Cookie"); assertTrue(sessionCookie != null); assertFalse(testListener.isCalled()); // make a request to change the sessionid Request request = client.newRequest( "http://localhost:" + port + contextPath + servletMapping + "?action=renew"); request.header("Cookie", sessionCookie); ContentResponse renewResponse = request.send(); assertEquals(HttpServletResponse.SC_OK, renewResponse.getStatus()); String renewSessionCookie = renewResponse.getHeaders().get("Set-Cookie"); assertNotNull(renewSessionCookie); assertNotSame(sessionCookie, renewSessionCookie); assertTrue(testListener.isCalled()); assertTrue( verifyChange( context, AbstractTestServer.extractSessionId(sessionCookie), AbstractTestServer.extractSessionId(renewSessionCookie))); } finally { client.stop(); _server.stop(); } }
@Test public void testProxyWithBigRequestContentConsumed() throws Exception { final byte[] content = new byte[128 * 1024]; new Random().nextBytes(content); prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); InputStream input = req.getInputStream(); int index = 0; while (true) { int value = input.read(); if (value < 0) break; Assert.assertEquals( "Content mismatch at index=" + index, content[index] & 0xFF, value); ++index; } } }); ContentResponse response = client .newRequest("localhost", serverConnector.getLocalPort()) .method(HttpMethod.POST) .content(new BytesContentProvider(content)) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); }
@Test public void testProxyWithRequestContentAndResponseContent() throws Exception { prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); IO.copy(req.getInputStream(), resp.getOutputStream()); } }); byte[] content = new byte[1024]; new Random().nextBytes(content); ContentResponse response = client .newRequest("localhost", serverConnector.getLocalPort()) .method(HttpMethod.POST) .content(new BytesContentProvider(content)) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); Assert.assertArrayEquals(content, response.getContent()); }
@Test public void testResponseHeadersAreNotRemoved() throws Exception { prepareProxy(); proxyContext.stop(); final String headerName = "X-Test"; final String headerValue = "test-value"; proxyContext.addFilter( new FilterHolder( new Filter() { @Override public void init(FilterConfig filterConfig) throws ServletException {} @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { ((HttpServletResponse) response).addHeader(headerName, headerValue); chain.doFilter(request, response); } @Override public void destroy() {} }), "/*", EnumSet.of(DispatcherType.REQUEST)); proxyContext.start(); prepareServer(new EmptyHttpServlet()); HttpClient client = prepareClient(); ContentResponse response = client.newRequest("localhost", serverConnector.getLocalPort()).send(); Assert.assertEquals(200, response.getStatus()); Assert.assertEquals(headerValue, response.getHeaders().get(headerName)); }
@Override public ClientResponse apply(final ClientRequest jerseyRequest) throws ProcessingException { final Request jettyRequest = translateRequest(jerseyRequest); final Map<String, String> clientHeadersSnapshot = writeOutBoundHeaders(jerseyRequest.getHeaders(), jettyRequest); final ContentProvider entity = getBytesProvider(jerseyRequest); if (entity != null) { jettyRequest.content(entity); } try { final ContentResponse jettyResponse = jettyRequest.send(); HeaderUtils.checkHeaderChanges( clientHeadersSnapshot, jerseyRequest.getHeaders(), JettyConnector.this.getClass().getName()); final javax.ws.rs.core.Response.StatusType status = jettyResponse.getReason() == null ? Statuses.from(jettyResponse.getStatus()) : Statuses.from(jettyResponse.getStatus(), jettyResponse.getReason()); final ClientResponse jerseyResponse = new ClientResponse(status, jerseyRequest); processResponseHeaders(jettyResponse.getHeaders(), jerseyResponse); try { jerseyResponse.setEntityStream(new HttpClientResponseInputStream(jettyResponse)); } catch (final IOException e) { LOGGER.log(Level.SEVERE, null, e); } return jerseyResponse; } catch (final Exception e) { throw new ProcessingException(e); } }
@Test public void testGZIPContentIsProxied() throws Exception { final byte[] content = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); resp.addHeader("Content-Encoding", "gzip"); GZIPOutputStream gzipOutputStream = new GZIPOutputStream(resp.getOutputStream()); gzipOutputStream.write(content); gzipOutputStream.close(); } }); ContentResponse response = client .newRequest("localhost", serverConnector.getLocalPort()) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); Assert.assertArrayEquals(content, response.getContent()); }
@Test public void testTransparentProxyWithoutPrefix() throws Exception { final String target = "/test"; prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); resp.setStatus(target.equals(req.getRequestURI()) ? 200 : 404); } }); final String proxyTo = "http://localhost:" + serverConnector.getLocalPort(); proxyServlet = new ProxyServlet.Transparent(); Map<String, String> initParams = new HashMap<>(); initParams.put("proxyTo", proxyTo); prepareProxy(initParams); // Make the request to the proxy, it should transparently forward to the server ContentResponse response = client .newRequest("localhost", proxyConnector.getLocalPort()) .path(target) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); }
@Test public void testSessionMigration() throws Exception { String contextPath = ""; String servletMapping = "/server"; AbstractTestServer server1 = createServer(0); server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping); try { server1.start(); int port1 = server1.getPort(); AbstractTestServer server2 = createServer(0); server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping); try { server2.start(); int port2 = server2.getPort(); HttpClient client = new HttpClient(); client.start(); try { // Perform one request to server1 to create a session int value = 1; Request request1 = client.POST( "http://localhost:" + port1 + contextPath + servletMapping + "?action=set&value=" + value); ContentResponse response1 = request1.send(); assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); String sessionCookie = response1.getHeaders().get("Set-Cookie"); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // Perform a request to server2 using the session cookie from the previous request // This should migrate the session from server1 to server2. Request request2 = client.newRequest( "http://localhost:" + port2 + contextPath + servletMapping + "?action=get"); request2.header("Cookie", sessionCookie); ContentResponse response2 = request2.send(); assertEquals(HttpServletResponse.SC_OK, response2.getStatus()); String response = response2.getContentAsString(); assertEquals(response.trim(), String.valueOf(value)); } finally { client.stop(); } } finally { server2.stop(); } } finally { server1.stop(); } }
@Test public void testAttributeNamesWithDots() throws Exception { String contextPath = ""; String servletMapping = "/server"; int maxInactivePeriod = 10000; int scavengePeriod = 20000; AbstractTestServer server1 = createServer(0, maxInactivePeriod, scavengePeriod); server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping); server1.start(); int port1 = server1.getPort(); AbstractTestServer server2 = createServer(0, maxInactivePeriod, scavengePeriod); server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping); server2.start(); int port2 = server2.getPort(); try { HttpClient client = new HttpClient(); client.start(); try { // Perform one request to server1 to create a session with attribute with dotted name ContentResponse response = client.GET("http://localhost:" + port1 + contextPath + servletMapping + "?action=init"); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); String resp = response.getContentAsString(); String[] sessionTestResponse = resp.split("/"); assertEquals("a.b.c", sessionTestResponse[0]); String sessionCookie = response.getHeaders().get(HttpHeader.SET_COOKIE); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // Make a request to the 2nd server which will do a refresh, use TestServlet to ensure that // the // session attribute with dotted name is not removed Request request2 = client.newRequest( "http://localhost:" + port2 + contextPath + servletMapping + "?action=get"); request2.header("Cookie", sessionCookie); ContentResponse response2 = request2.send(); assertEquals(HttpServletResponse.SC_OK, response2.getStatus()); } finally { client.stop(); } } finally { server1.stop(); server2.stop(); } }
/** * If nodeA creates a session, and just afterwards crashes, it is the only node that knows about * the session. We want to test that the session data is gone after scavenging. */ @Test public void testOrphanedSession() throws Exception { // Disable scavenging for the first server, so that we simulate its "crash". String contextPath = ""; String servletMapping = "/server"; int inactivePeriod = 5; AbstractTestServer server1 = createServer(0, inactivePeriod, -1); server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping); try { server1.start(); int port1 = server1.getPort(); int scavengePeriod = 2; AbstractTestServer server2 = createServer(0, inactivePeriod, scavengePeriod); server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping); try { server2.start(); int port2 = server2.getPort(); HttpClient client = new HttpClient(); client.start(); try { // Connect to server1 to create a session and get its session cookie ContentResponse response1 = client.GET( "http://localhost:" + port1 + contextPath + servletMapping + "?action=init"); assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // Wait for the session to expire. // The first node does not do any scavenging, but the session // must be removed by scavenging done in the other node. Thread.sleep(TimeUnit.SECONDS.toMillis(inactivePeriod + 2L * scavengePeriod)); // Perform one request to server2 to be sure that the session has been expired Request request = client.newRequest( "http://localhost:" + port2 + contextPath + servletMapping + "?action=check"); request.header("Cookie", sessionCookie); ContentResponse response2 = request.send(); assertEquals(HttpServletResponse.SC_OK, response2.getStatus()); } finally { client.stop(); } } finally { server2.stop(); } } finally { server1.stop(); } }
@Test @Ignore("failing because an http cookie with null value is coming over as \"null\"") public void testSessionCookie() throws Exception { String contextPath = ""; String servletMapping = "/server"; int scavengePeriod = 3; AbstractTestServer server = createServer(0, 1, scavengePeriod); ServletContextHandler context = server.addContext(contextPath); context.addServlet(TestServlet.class, servletMapping); try { server.start(); int port = server.getPort(); HttpClient client = new HttpClient(); client.start(); try { ContentResponse response = client.GET( "http://localhost:" + port + contextPath + servletMapping + "?action=create"); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); String sessionCookie = response.getHeaders().get("Set-Cookie"); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. // sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // Let's wait for the scavenger to run, waiting 2.5 times the scavenger period // pause(scavengePeriod); Request request = client.newRequest( "http://localhost:" + port + contextPath + servletMapping + "?action=check-cookie"); request.header("Cookie", sessionCookie); response = request.send(); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); request = client.newRequest( "http://localhost:" + port + contextPath + servletMapping + "?action=null-cookie"); request.header("Cookie", sessionCookie); response = request.send(); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); } finally { client.stop(); } } finally { server.stop(); } }
@Test public void testProxyWithoutContent() throws Exception { prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); } }); ContentResponse response = client .newRequest("localhost", serverConnector.getLocalPort()) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals("OK", response.getReason()); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); }
@Test public void testTransparentProxyWithQueryWithSpaces() throws Exception { final String target = "/test"; final String query = "a=1&b=2&c=1234%205678&d=hello+world"; prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); if (target.equals(req.getRequestURI())) { if (query.equals(req.getQueryString())) { resp.setStatus(200); return; } } resp.setStatus(404); } }); String proxyTo = "http://localhost:" + serverConnector.getLocalPort(); String prefix = "/proxy"; proxyServlet = new ProxyServlet.Transparent(); Map<String, String> params = new HashMap<>(); params.put("proxyTo", proxyTo); params.put("prefix", prefix); prepareProxy(params); // Make the request to the proxy, it should transparently forward to the server ContentResponse response = client .newRequest("localhost", proxyConnector.getLocalPort()) .path(prefix + target + "?" + query) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); }
@Test public void testCookiesFromDifferentClientsAreNotMixed() throws Exception { final String name = "biscuit"; prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); String value = req.getHeader(name); if (value != null) { Cookie cookie = new Cookie(name, value); cookie.setMaxAge(3600); resp.addCookie(cookie); } else { Cookie[] cookies = req.getCookies(); Assert.assertEquals(1, cookies.length); } } }); String value1 = "1"; ContentResponse response1 = client .newRequest("localhost", serverConnector.getLocalPort()) .header(name, value1) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response1.getStatus()); Assert.assertTrue(response1.getHeaders().containsKey(PROXIED_HEADER)); List<HttpCookie> cookies = client.getCookieStore().getCookies(); Assert.assertEquals(1, cookies.size()); Assert.assertEquals(name, cookies.get(0).getName()); Assert.assertEquals(value1, cookies.get(0).getValue()); HttpClient client2 = prepareClient(); String value2 = "2"; ContentResponse response2 = client2 .newRequest("localhost", serverConnector.getLocalPort()) .header(name, value2) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response2.getStatus()); Assert.assertTrue(response2.getHeaders().containsKey(PROXIED_HEADER)); cookies = client2.getCookieStore().getCookies(); Assert.assertEquals(1, cookies.size()); Assert.assertEquals(name, cookies.get(0).getName()); Assert.assertEquals(value2, cookies.get(0).getValue()); // Make a third request to be sure the proxy does not mix cookies ContentResponse response3 = client .newRequest("localhost", serverConnector.getLocalPort()) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response3.getStatus()); Assert.assertTrue(response3.getHeaders().containsKey(PROXIED_HEADER)); }
@Test public void testInvalidation() throws Exception { String contextPath = ""; String servletMapping = "/server"; AbstractTestServer server1 = createServer(0); server1.addContext(contextPath).addServlet(TestServlet.class, servletMapping); server1.start(); int port1 = server1.getPort(); System.err.println("Port1=" + port1); try { AbstractTestServer server2 = createServer(0); server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping); server2.start(); int port2 = server2.getPort(); System.err.println("port2=" + port2); try { HttpClient client = new HttpClient(); QueuedThreadPool executor = new QueuedThreadPool(); client.setExecutor(executor); client.start(); try { String[] urls = new String[2]; urls[0] = "http://localhost:" + port1 + contextPath + servletMapping; urls[1] = "http://localhost:" + port2 + contextPath + servletMapping; // Create the session on node1 ContentResponse response1 = client.GET(urls[0] + "?action=init"); assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // Be sure the session is also present in node2 Request request2 = client.newRequest(urls[1] + "?action=increment"); request2.header("Cookie", sessionCookie); ContentResponse response2 = request2.send(); assertEquals(HttpServletResponse.SC_OK, response2.getStatus()); // Invalidate on node1 Request request1 = client.newRequest(urls[0] + "?action=invalidate"); request1.header("Cookie", sessionCookie); response1 = request1.send(); assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); pause(); // Be sure on node2 we don't see the session anymore request2 = client.newRequest(urls[1] + "?action=test"); request2.header("Cookie", sessionCookie); response2 = request2.send(); assertEquals(HttpServletResponse.SC_OK, response2.getStatus()); } finally { client.stop(); } } finally { server2.stop(); } } finally { server1.stop(); } }
@Test public void testRemoveSession() throws Exception { String contextPath = ""; String servletMapping = "/server"; int scavengePeriod = 3; AbstractTestServer server = createServer(0, 1, scavengePeriod); ServletContextHandler context = server.addContext(contextPath); context.addServlet(TestServlet.class, servletMapping); TestEventListener testListener = new TestEventListener(); context.getSessionHandler().addEventListener(testListener); AbstractSessionManager m = (AbstractSessionManager) context.getSessionHandler().getSessionManager(); try { server.start(); int port = server.getPort(); HttpClient client = new HttpClient(); client.start(); try { ContentResponse response = client.GET( "http://localhost:" + port + contextPath + servletMapping + "?action=create"); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); String sessionCookie = response.getHeaders().get("Set-Cookie"); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // ensure sessionCreated listener is called assertTrue(testListener.isCreated()); assertEquals(1, m.getSessions()); assertEquals(1, m.getSessionsMax()); assertEquals(1, m.getSessionsTotal()); // now delete the session Request request = client.newRequest( "http://localhost:" + port + contextPath + servletMapping + "?action=delete"); request.header("Cookie", sessionCookie); response = request.send(); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); // ensure sessionDestroyed listener is called assertTrue(testListener.isDestroyed()); assertEquals(0, m.getSessions()); assertEquals(1, m.getSessionsMax()); assertEquals(1, m.getSessionsTotal()); // The session is not there anymore, even if we present an old cookie request = client.newRequest( "http://localhost:" + port + contextPath + servletMapping + "?action=check"); request.header("Cookie", sessionCookie); response = request.send(); assertEquals(HttpServletResponse.SC_OK, response.getStatus()); assertEquals(0, m.getSessions()); assertEquals(1, m.getSessionsMax()); assertEquals(1, m.getSessionsTotal()); } finally { client.stop(); } } finally { server.stop(); } }
@Test public void testLastAccessTime() throws Exception { String contextPath = ""; String servletMapping = "/server"; int maxInactivePeriod = 8; // session will timeout after 8 seconds int scavengePeriod = 2; // scavenging occurs every 2 seconds AbstractTestServer server1 = createServer(0, maxInactivePeriod, scavengePeriod); TestServlet servlet1 = new TestServlet(); ServletHolder holder1 = new ServletHolder(servlet1); ServletContextHandler context = server1.addContext(contextPath); TestSessionListener listener1 = new TestSessionListener(); context.addEventListener(listener1); context.addServlet(holder1, servletMapping); server1.start(); int port1 = server1.getPort(); try { AbstractTestServer server2 = createServer(0, maxInactivePeriod, scavengePeriod); server2.addContext(contextPath).addServlet(TestServlet.class, servletMapping); server2.start(); int port2 = server2.getPort(); try { HttpClient client = new HttpClient(); client.start(); try { // Perform one request to server1 to create a session Future<ContentResponse> future = client.GET( "http://localhost:" + port1 + contextPath + servletMapping + "?action=init"); ContentResponse response1 = future.get(); assertEquals(HttpServletResponse.SC_OK, response1.getStatus()); assertEquals("test", response1.getContentAsString()); String sessionCookie = response1.getHeaders().getStringField("Set-Cookie"); assertTrue(sessionCookie != null); // Mangle the cookie, replacing Path with $Path, etc. sessionCookie = sessionCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); // Perform some request to server2 using the session cookie from the previous request // This should migrate the session from server1 to server2, and leave server1's // session in a very stale state, while server2 has a very fresh session. // We want to test that optimizations done to the saving of the shared lastAccessTime // do not break the correct working int requestInterval = 500; for (int i = 0; i < maxInactivePeriod * (1000 / requestInterval); ++i) { Request request = client.newRequest("http://localhost:" + port2 + contextPath + servletMapping); request.header("Cookie", sessionCookie); future = request.send(); ContentResponse response2 = future.get(); assertEquals(HttpServletResponse.SC_OK, response2.getStatus()); assertEquals("test", response2.getContentAsString()); String setCookie = response2.getHeaders().getStringField("Set-Cookie"); if (setCookie != null) sessionCookie = setCookie.replaceFirst("(\\W)(P|p)ath=", "$1\\$Path="); Thread.sleep(requestInterval); } // At this point, session1 should be eligible for expiration. // Let's wait for the scavenger to run, waiting 2.5 times the scavenger period Thread.sleep(scavengePeriod * 2500L); // check that the session was not scavenged over on server1 by ensuring that the // SessionListener destroy method wasn't called assertTrue(listener1.destroyed == false); } finally { client.stop(); } } finally { server2.stop(); } } finally { server1.stop(); } }
@Test public void testCachingProxy() throws Exception { final byte[] content = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF}; prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { if (req.getHeader("Via") != null) resp.addHeader(PROXIED_HEADER, "true"); resp.getOutputStream().write(content); } }); // Don't do this at home: this example is not concurrent, not complete, // it is only used for this test and to verify that ProxyServlet can be // subclassed enough to write your own caching servlet final String cacheHeader = "X-Cached"; proxyServlet = new ProxyServlet() { private Map<String, ContentResponse> cache = new HashMap<>(); private Map<String, ByteArrayOutputStream> temp = new HashMap<>(); @Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ContentResponse cachedResponse = cache.get(request.getRequestURI()); if (cachedResponse != null) { response.setStatus(cachedResponse.getStatus()); // Should copy headers too, but keep it simple response.addHeader(cacheHeader, "true"); response.getOutputStream().write(cachedResponse.getContent()); } else { super.service(request, response); } } @Override protected void onResponseContent( HttpServletRequest request, HttpServletResponse response, Response proxyResponse, byte[] buffer, int offset, int length, Callback callback) { // Accumulate the response content ByteArrayOutputStream baos = temp.get(request.getRequestURI()); if (baos == null) { baos = new ByteArrayOutputStream(); temp.put(request.getRequestURI(), baos); } baos.write(buffer, offset, length); super.onResponseContent( request, response, proxyResponse, buffer, offset, length, callback); } @Override protected void onResponseSuccess( HttpServletRequest request, HttpServletResponse response, Response proxyResponse) { byte[] content = temp.remove(request.getRequestURI()).toByteArray(); ContentResponse cached = new HttpContentResponse(proxyResponse, content, null, null); cache.put(request.getRequestURI(), cached); super.onResponseSuccess(request, response, proxyResponse); } }; prepareProxy(); // First request ContentResponse response = client .newRequest("localhost", serverConnector.getLocalPort()) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(PROXIED_HEADER)); Assert.assertArrayEquals(content, response.getContent()); // Second request should be cached response = client .newRequest("localhost", serverConnector.getLocalPort()) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertTrue(response.getHeaders().containsKey(cacheHeader)); Assert.assertArrayEquals(content, response.getContent()); }