private void testClientConnectionHandler(boolean local, boolean global) throws Exception { server.requestHandler(req -> { req.response().end(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); AtomicInteger status = new AtomicInteger(); Handler<HttpConnection> handler = conn -> status.getAndIncrement(); if (global) { client.connectionHandler(handler); } HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> { assertEquals((local ? 1 : 0) + (global ? 1 : 0), status.getAndIncrement()); testComplete(); }); if (local) { req.connectionHandler(handler); } req.end(); await(); }
@Test public void testClientConnectionExceptionHandler() throws Exception { server.requestHandler(req -> { NetSocket so = req.netSocket(); so.write(Buffer.buffer(TestUtils.randomAlphaString(40) + "\r\n")); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> { }); req.connectionHandler(conn -> { conn.exceptionHandler(err -> { testComplete(); }); }); req.sendHead(); await(); }
private void testParamDecoding(String value) throws UnsupportedEncodingException { server.requestHandler(req -> { req.setExpectMultipart(true); req.endHandler(v -> { MultiMap formAttributes = req.formAttributes(); assertEquals(value, formAttributes.get("param")); }); req.response().end(); }); String postData = "param=" + URLEncoder.encode(value,"UTF-8"); server.listen(onSuccess(server -> { client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onSuccess(resp -> testComplete())) .putHeader(HttpHeaders.CONTENT_TYPE, HttpHeaders.APPLICATION_X_WWW_FORM_URLENCODED) .putHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(postData.length())) .write(postData).end(); })); await(); }
@Test public void testServerExceptionHandler() throws Exception { server.exceptionHandler(err -> { assertTrue(err instanceof TooLongFrameException); testComplete(); }); server.requestHandler(req -> { fail(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> { }); req.putHeader("the_header", TestUtils.randomAlphaString(10000)); req.sendHead(); await(); }
@Test public void testServerConnectionClose() throws Exception { // Test server connection close + client close handler server.requestHandler(req -> { req.connection().close(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onFailure(err -> { })) .connectionHandler(conn -> { conn.closeHandler(v -> { testComplete(); }); }).sendHead(); await(); }
@Test public void testConnectionCloseDuringShouldCallHandleExceptionOnlyOnce() throws Exception { server.requestHandler(req -> { vertx.setTimer(500, id -> { req.connection().close(); }); }); AtomicInteger count = new AtomicInteger(); startServer(); HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onFailure(res -> {})); post.setChunked(true); post.write(TestUtils.randomBuffer(10000)); CountDownLatch latch = new CountDownLatch(1); post.exceptionHandler(x-> { count.incrementAndGet(); vertx.setTimer(10, id -> { latch.countDown(); }); }); // then stall until timeout and the exception handler will be called. awaitLatch(latch); assertEquals(count.get(), 1); }
@Test public void testClientConnectionClose() throws Exception { // Test client connection close + server close handler CountDownLatch latch = new CountDownLatch(1); server.requestHandler(req -> { AtomicInteger len = new AtomicInteger(); req.handler(buff -> { if (len.addAndGet(buff.length()) == 1024) { latch.countDown(); } }); req.connection().closeHandler(v -> { testComplete(); }); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onFailure(err -> {})); req.setChunked(true); req.write(TestUtils.randomBuffer(1024)); awaitLatch(latch); req.connection().close(); await(); }
private void testPost(String expected) throws Exception { Buffer content = Buffer.buffer(); AtomicInteger count = new AtomicInteger(); server.requestHandler(req -> { assertEquals(HttpMethod.POST, req.method()); req.handler(buff -> { content.appendBuffer(buff); count.getAndIncrement(); }); req.endHandler(v -> { assertTrue(count.get() > 0); req.response().end(); }); }); startServer(); client.post(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onSuccess(resp -> { resp.endHandler(v -> { assertEquals(expected, content.toString()); testComplete(); }); })).exceptionHandler(err -> { fail(); }).end(expected); await(); }
@Test public void testBytesReadRequest() throws Exception { int length = 2048; Buffer expected = Buffer.buffer(TestUtils.randomAlphaString(length));; server.requestHandler(req -> { req.bodyHandler(buffer -> { assertEquals(req.bytesRead(), length); req.response().end(); }); }); startServer(); client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.bodyHandler(buff -> { testComplete(); }); })).exceptionHandler(this::fail) .putHeader("content-length", String.valueOf(length)) .write(expected) .end(); await(); }
@Test public void testServerConnectionExceptionHandler() throws Exception { server.connectionHandler(conn -> { conn.exceptionHandler(err -> { assertTrue(err instanceof TooLongFrameException); testComplete(); }); }); server.requestHandler(req -> { req.response().end(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); client.close(); client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1)); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp1 -> { HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp2 -> { }); req.putHeader("the_header", TestUtils.randomAlphaString(10000)); req.sendHead(); }); await(); }
@Test public void testPipelinedWithPendingResponse() throws Exception { int numReq = 10; waitFor(numReq); AtomicInteger inflight = new AtomicInteger(); AtomicInteger count = new AtomicInteger(); server.requestHandler(req -> { int val = count.getAndIncrement(); assertEquals(0, inflight.getAndIncrement()); vertx.setTimer(100, v -> { inflight.decrementAndGet(); req.response().end("" + val); }); }); startServer(); client.close(); client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true)); for (int i = 0;i < numReq;i++) { String expected = "" + i; client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onSuccess(resp -> { resp.bodyHandler(body -> { assertEquals(expected, body.toString()); complete(); }); })).end(TestUtils.randomAlphaString(1024)); } await(); }
@Test public void testResetClientRequestNotYetSent() throws Exception { waitFor(2); server.close(); server = vertx.createHttpServer(createBaseServerOptions().setInitialSettings(new Http2Settings().setMaxConcurrentStreams(1))); AtomicInteger numReq = new AtomicInteger(); server.requestHandler(req -> { assertEquals(0, numReq.getAndIncrement()); req.response().end(); complete(); }); startServer(); HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> { fail(); }); post.setChunked(true).write(TestUtils.randomBuffer(1024)); assertTrue(post.reset()); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> { assertEquals(1, numReq.get()); complete(); }); await(); }
@Test public void testClientRequestExceptionHandlerCalledWhenConnectionClosed() throws Exception { server.requestHandler(req -> { req.handler(buff -> { req.connection().close(); }); }); startServer(); HttpClientRequest req = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onFailure(err -> {})).setChunked(true); req.exceptionHandler(err -> { testComplete(); }); req.write("chunk"); await(); }
@Test public void testHandleInvalid204Response() throws Exception { int numReq = 3; waitFor(numReq); client.close(); client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setKeepAlive(true).setMaxPoolSize(1)); server.requestHandler(r -> { // Generate an invalid response for the pipe-lined r.response().setChunked(true).setStatusCode(204).end(); }).listen(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, onSuccess(v1 -> { for (int i = 0;i < numReq;i++) { AtomicInteger count = new AtomicInteger(); HttpClientRequest post = client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(r -> { r.endHandler(v2 -> { complete(); }); })).exceptionHandler(err -> { if (count.incrementAndGet() == 1) { complete(); } }); post.end(); } })); await(); }
@Test // Client provides SNI and server responds with a matching certificate for the indicated server name public void testSNIWithHostHeader() throws Exception { X509Certificate cert = testTLS(Cert.NONE, Trust.SNI_JKS_HOST2, Cert.SNI_JKS, Trust.NONE) .serverSni() .requestProvider((client, handler) -> client.post(4043, "localhost", "/somepath", handler).setHost("host2.com:4043")) .pass() .clientPeerCert(); assertEquals("host2.com", TestUtils.cnOf(cert)); }
@Test public void testDeferredRequestEnd() throws Exception { server.requestHandler(req -> { req.pause(); req.bodyHandler(body -> { assertTrue(req.isEnded()); req.response().end(body); }); vertx.setTimer(10, v -> { assertFalse(req.isEnded()); req.resume(); }); }); startServer(); Buffer expected = Buffer.buffer(TestUtils.randomAlphaString(1024)); client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onSuccess(resp -> { resp.bodyHandler(body -> { assertEquals(expected, body); testComplete(); }); })).end(expected); await(); }
@Test public void testBeginPipelinedRequestByResponseSentBeforeRequestCompletion() throws Exception { server.requestHandler(req -> { if (req.method() == HttpMethod.POST) { req.pause(); vertx.setTimer(100, id1 -> { req.response().end(); vertx.setTimer(100, id2 -> { req.resume(); }); }); } else if (req.method() == HttpMethod.GET) { req.response().end(); } }); startServer(); client.close(); client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true)); client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> { }).end(TestUtils.randomAlphaString(1024)); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> { testComplete(); }); await(); }
@Test public void testBeginPipelinedRequestByResponseSentOnRequestCompletion() throws Exception { server.requestHandler(req -> { if (req.method() == HttpMethod.POST) { req.pause(); vertx.setTimer(100, id -> { req.resume(); }); } req.endHandler(v -> { req.response().end(); }); }); startServer(); client.close(); client = vertx.createHttpClient(new HttpClientOptions().setPipelining(true).setMaxPoolSize(1).setKeepAlive(true)); client.post(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> { }).end(TestUtils.randomAlphaString(1024)); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> { testComplete(); }); await(); }
@Test public void testServerResetClientStreamDuringRequest() throws Exception { String chunk = TestUtils.randomAlphaString(1024); server.requestHandler(req -> { req.handler(buf -> { req.response().reset(8); }); }); startServer(); client.post(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onFailure(resp -> {})) .exceptionHandler(err -> { Context ctx = Vertx.currentContext(); assertOnIOContext(ctx); assertTrue(err instanceof StreamResetException); StreamResetException reset = (StreamResetException) err; assertEquals(8, reset.getCode()); testComplete(); }).setChunked(true).write(chunk); await(); }
@Test public void testServerResetClientStreamDuringResponse() throws Exception { waitFor(2); String chunk = TestUtils.randomAlphaString(1024); Future<Void> doReset = Future.future(); server.requestHandler(req -> { doReset.setHandler(onSuccess(v -> { req.response().reset(8); })); req.response().setChunked(true).write(Buffer.buffer(chunk)); }); startServer(); Context ctx = vertx.getOrCreateContext(); Handler<Throwable> resetHandler = err -> { assertOnIOContext(ctx); assertTrue(err instanceof StreamResetException); StreamResetException reset = (StreamResetException) err; assertEquals(8, reset.getCode()); complete(); }; ctx.runOnContext(v -> { client.post(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onSuccess(resp -> { resp.exceptionHandler(resetHandler); resp.handler(buff -> { doReset.complete(); }); })).exceptionHandler(resetHandler).setChunked(true).write(chunk); }); await(); }