protected String doContentRequest( String wsPart, String content, int expectedResponse, String expectedContent, HttpMethod method) { try { final ContentResponse contentResponse = doRequest(wsPart, method, content); System.err.println(content); dumpError(expectedResponse, contentResponse); Assert.assertEquals(expectedResponse, contentResponse.getStatus()); if (expectedResponse == 500) { // no content available anyway return ""; //$NON-NLS-1$ } final String retContent = contentResponse.getContentAsString(); System.err.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>"); System.err.println(retContent); if (expectedContent != null && retContent.indexOf(expectedContent) == -1) { System.err.println(retContent); Assert.fail(); } return retContent; } catch (final Exception e) { throw new IllegalStateException(e); } }
@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(); } }
private void dumpError(int expectedResponseCode, ContentResponse response) throws Exception { if (expectedResponseCode != response.getStatus() && response.getStatus() == HttpServletResponse.SC_INTERNAL_SERVER_ERROR) { final String content = response.getContentAsString(); if (content.contains("response:error")) { // $NON-NLS-1$ final ErrorType errorType = (ErrorType) deserialize(content).get(0); System.err.println(errorType.getMessage()); System.err.println(errorType.getStackTrace()); } } }
@Test public void testConcurrentHandshakeFailureAndPublish() throws Exception { bayeux.setSecurityPolicy(new Policy()); final String channelName = "/foo"; final AtomicBoolean publish = new AtomicBoolean(); new BroadcastChannelService(bayeux, channelName, publish); // A bad sequence of messages that clients should prevent // (by not allowing a publish until the handshake is completed) // yet the server must behave properly Request handshake = newBayeuxRequest( "[{" + "\"channel\": \"/meta/handshake\"," + "\"version\": \"1.0\"," + "\"minimumVersion\": \"1.0\"," + "\"supportedConnectionTypes\": [\"long-polling\"]" + "}, {" + "\"clientId\": null," + "\"channel\": \"" + channelName + "\"," + "\"data\": {}" + "}]"); ContentResponse response = handshake.send(); Assert.assertEquals(200, response.getStatus()); JSONContext.Client jsonContext = new JettyJSONContextClient(); Message.Mutable[] messages = jsonContext.parse(response.getContentAsString()); Assert.assertEquals(2, messages.length); Message handshakeResponse = messages[0]; Assert.assertFalse(handshakeResponse.isSuccessful()); String handshakeError = (String) handshakeResponse.get("error"); Assert.assertNotNull(handshakeError); Assert.assertTrue(handshakeError.contains("403")); Map<String, Object> advice = handshakeResponse.getAdvice(); Assert.assertNotNull(advice); Assert.assertEquals(Message.RECONNECT_NONE_VALUE, advice.get("reconnect")); Message publishResponse = messages[1]; Assert.assertFalse(publishResponse.isSuccessful()); String publishError = (String) publishResponse.get("error"); Assert.assertNotNull(publishError); Assert.assertTrue(publishError.contains("402")); Assert.assertNull(publishResponse.getAdvice()); Assert.assertFalse(publish.get()); }
protected String doGetRequest(String wsPart, String testContent, int responseCode) { try { final ContentResponse contentResponse = doRequest(wsPart, HttpMethod.GET, null); dumpError(responseCode, contentResponse); final String content = contentResponse.getContentAsString(); System.err.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>"); System.err.println(content); Assert.assertEquals(responseCode, contentResponse.getStatus()); if (testContent != null && content.indexOf(testContent) == -1) { System.err.println(content); Assert.fail(); } return content; } catch (final Exception e) { throw new IllegalStateException("Exception when executing ws: " + wsPart, e); // $NON-NLS-1$ } }
@Test public void testProxyXForwardedHostHeaderIsPresent() throws Exception { prepareProxy(); prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { PrintWriter writer = resp.getWriter(); writer.write(req.getHeader("X-Forwarded-Host")); writer.flush(); } }); ContentResponse response = client.GET("http://localhost:" + serverConnector.getLocalPort()); Assert.assertThat( "Response expected to contain content of X-Forwarded-Host Header from the request", response.getContentAsString(), Matchers.equalTo("localhost:" + serverConnector.getLocalPort())); }
@Test public void testProxyWithQueryString() throws Exception { prepareProxy(); String query = "a=1&b=%E2%82%AC"; prepareServer( new HttpServlet() { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.getOutputStream().print(req.getQueryString()); } }); ContentResponse response = client .newRequest("http://localhost:" + serverConnector.getLocalPort() + "/?" + query) .timeout(5, TimeUnit.SECONDS) .send(); Assert.assertEquals(200, response.getStatus()); Assert.assertEquals(query, response.getContentAsString()); }
@Test public void testIdleLongPollDoesNotCauseMultipleClientsAdvice() throws Exception { startServer(null); final long timeout = 2000; final long sleep = 500; bayeux.setTransports( new JSONTransport(bayeux) { { setOption(TIMEOUT_OPTION, timeout); init(); } @Override protected LongPollScheduler newLongPollScheduler( ServerSessionImpl session, AsyncContext asyncContext, ServerMessage.Mutable metaConnectReply, String browserId) { return new LongPollScheduler(session, asyncContext, metaConnectReply, browserId) { private final AtomicInteger decrements = new AtomicInteger(); @Override public void onComplete(final AsyncEvent asyncEvent) throws IOException { if (decrements.incrementAndGet() == 1) { // Simulate that onComplete() is delayed without blocking // this thread, to cause a race condition new Thread() { @Override public void run() { try { Thread.sleep(sleep); superOnComplete(asyncEvent); } catch (Exception x) { x.printStackTrace(); } } }.start(); } else { superOnComplete(asyncEvent); } } private void superOnComplete(AsyncEvent asyncEvent) throws IOException { super.onComplete(asyncEvent); } }; } }); Request handshake = newBayeuxRequest( "[{" + "\"channel\": \"/meta/handshake\"," + "\"version\": \"1.0\"," + "\"minimumVersion\": \"1.0\"," + "\"supportedConnectionTypes\": [\"long-polling\"]" + "}]"); ContentResponse response = handshake.send(); Assert.assertEquals(200, response.getStatus()); String clientId = extractClientId(response); Request connect1 = newBayeuxRequest( "[{" + "\"channel\": \"/meta/connect\"," + "\"clientId\": \"" + clientId + "\"," + "\"connectionType\": \"long-polling\"" + "}]"); response = connect1.send(); Assert.assertEquals(200, response.getStatus()); ServerSession serverSession = bayeux.getSession(clientId); Assert.assertNotNull(serverSession); Request connect2 = newBayeuxRequest( "[{" + "\"channel\": \"/meta/connect\"," + "\"clientId\": \"" + clientId + "\"," + "\"connectionType\": \"long-polling\"" + "}]"); response = connect2.send(); Assert.assertEquals(200, response.getStatus()); Request connect3 = newBayeuxRequest( "[{" + "\"channel\": \"/meta/connect\"," + "\"clientId\": \"" + clientId + "\"," + "\"connectionType\": \"long-polling\"" + "}]"); response = connect3.send(); Assert.assertEquals(200, response.getStatus()); JSONContext.Client jsonContext = new JettyJSONContextClient(); Message.Mutable[] messages = jsonContext.parse(response.getContentAsString()); Assert.assertEquals(1, messages.length); Message.Mutable message = messages[0]; Map<String, Object> advice = message.getAdvice(); Assert.assertNull(advice); }
@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(); } }