@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(); }
@Test public void testConnectionErrorsGetReportedToHandlers() throws InterruptedException { CountDownLatch latch = new CountDownLatch(3); // This one should cause an error in the Client Exception handler, because it has no exception handler set specifically. HttpClientRequest req1 = client.request(HttpMethod.GET, 9998, DEFAULT_HTTP_HOST, "someurl1", onFailure(resp -> { latch.countDown(); })); req1.exceptionHandler(t -> { fail("Should not be called"); }); HttpClientRequest req2 = client.request(HttpMethod.GET, 9998, DEFAULT_HTTP_HOST, "someurl2", onFailure(resp -> { latch.countDown(); })); AtomicInteger req2Exceptions = new AtomicInteger(); req2.exceptionHandler(t -> { assertEquals("More than one call to req2 exception handler was not expected", 1, req2Exceptions.incrementAndGet()); latch.countDown(); }); req1.end(); req2.sendHead(); awaitLatch(latch); testComplete(); }
@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 testSendHeadersCompletionHandler() throws Exception { AtomicInteger status = new AtomicInteger(); server.requestHandler(req -> { req.response().end(); }); startServer(); HttpClientRequest req = client.request(HttpMethod.CONNECT, DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", onSuccess(resp -> { assertEquals(1, status.getAndIncrement()); resp.endHandler(v -> { assertEquals(2, status.getAndIncrement()); testComplete(); }); })); req.sendHead(version -> { assertEquals(0, status.getAndIncrement()); assertSame(HttpVersion.HTTP_2, version); req.end(); }); 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 testClientRequestWriteFromOtherThread() throws Exception { CountDownLatch latch1 = new CountDownLatch(1); CountDownLatch latch2 = new CountDownLatch(1); server.requestHandler(req -> { latch2.countDown(); req.endHandler(v -> { req.response().end(); }); }).listen(onSuccess(v -> { latch1.countDown(); })); awaitLatch(latch1); HttpClientRequest req = client.get(8080, "localhost", "/somepath", onSuccess(resp -> { assertEquals(200, resp.statusCode()); testComplete(); })).setChunked(true).sendHead(); awaitLatch(latch2); // The next write won't be buffered req.write("hello ").end("world"); await(); }
@Test public void testHttpClientRequestTimeoutResetsTheConnection() throws Exception { waitFor(3); server.requestHandler(req -> { AtomicBoolean errored = new AtomicBoolean(); req.exceptionHandler(err -> { if (errored.compareAndSet(false, true)) { complete(); } }); }); startServer(); HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(err -> { complete(); })); AtomicBoolean errored = new AtomicBoolean(); req.exceptionHandler(err -> { if (errored.compareAndSet(false, true)) { complete(); } }); CountDownLatch latch = new CountDownLatch(1); req.setChunked(true).sendHead(version -> latch.countDown()); awaitLatch(latch); req.setTimeout(100); await(); }
@Test public void testResponseDataTimeout() { Buffer expected = TestUtils.randomBuffer(1000); server.requestHandler(req -> { req.response().setChunked(true).write(expected); }); server.listen(onSuccess(s -> { Buffer received = Buffer.buffer(); HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.request().setTimeout(500); resp.handler(received::appendBuffer); })); AtomicInteger count = new AtomicInteger(); req.exceptionHandler(t -> { if (count.getAndIncrement() == 0) { assertTrue(t instanceof TimeoutException); assertEquals(expected, received); testComplete(); } }); req.sendHead(); })); await(); }
@Test public void testClientChaining() { server.requestHandler(noOpHandler()); server.listen(onSuccess(server -> { HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); assertTrue(req.setChunked(true) == req); assertTrue(req.sendHead() == req); assertTrue(req.write("foo", "UTF-8") == req); assertTrue(req.write("foo") == req); assertTrue(req.write(Buffer.buffer("foo")) == req); testComplete(); })); 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 testDontReuseConnectionWhenResponseEndsDuringAnOngoingRequest() throws Exception { client.close(); client = vertx.createHttpClient(new HttpClientOptions().setMaxPoolSize(1).setPipelining(true).setKeepAlive(true)); server.requestHandler(req -> { req.response().end(); }); CountDownLatch serverLatch = new CountDownLatch(1); server.listen(ar -> { assertTrue(ar.succeeded()); serverLatch.countDown(); }); awaitLatch(serverLatch); HttpClientRequest req1 = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onSuccess(resp -> { resp.endHandler(v1 -> { // End request after the response ended vertx.setTimer(100, v2 -> { resp.request().end(); }); }); })); // Send head to the server and trigger the request handler req1.sendHead(); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> { testComplete(); }).end(); await(); }
@Test public void testServerResponseResetFromOtherThread() throws Exception { waitFor(2); server.requestHandler(req -> { runAsync(() -> { req.response().reset(0); }); }).listen(onSuccess(v -> { client.get(8080, "localhost", "/somepath", onFailure(err -> { assertTrue(err instanceof StreamResetException); complete(); })).exceptionHandler(err -> { assertTrue(err instanceof StreamResetException); complete(); }).sendHead(); })); await(); }
@Test public void testHttpClientRequestShouldExceptionHandlerWhenTheClosedHandlerIsCalled() throws Exception { server = vertx.createHttpServer(new HttpServerOptions().setPort(DEFAULT_HTTP_PORT)).requestHandler(req -> { vertx.setTimer(1000, id -> { req.response().close(); }); }); startServer(); HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, HttpTestBase.DEFAULT_HTTP_HOST, "/someuri", resp -> { }).setChunked(true); CountDownLatch latch = new CountDownLatch(1); req.sendHead(version -> latch.countDown()); awaitLatch(latch); CheckingSender sender = new CheckingSender(vertx.getOrCreateContext(), req); req.exceptionHandler(err -> { Throwable failure = sender.close(); if (failure != null) { fail(failure); } else { testComplete(); } }); sender.send(); await(); }
@Test public void test100ContinueRejectedManually() throws Exception { server.close(); server = vertx.createHttpServer(createBaseServerOptions()); server.requestHandler(req -> { req.response().setStatusCode(405).end(); req.bodyHandler(data -> { fail("body should not be received"); }); }); server.listen(onSuccess(s -> { HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { assertEquals(405, resp.statusCode()); testComplete(); })); req.headers().set("Expect", "100-continue"); req.setChunked(true); req.continueHandler(v -> { fail("should not be called"); }); req.sendHead(); })); await(); }
@Test public void test100ContinueHandledAutomatically() throws Exception { Buffer toSend = TestUtils.randomBuffer(1000); server.requestHandler(req -> { req.bodyHandler(data -> { assertEquals(toSend, data); req.response().end(); }); }); server.listen(onSuccess(s -> { HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.endHandler(v -> testComplete()); })); req.headers().set("Expect", "100-continue"); req.setChunked(true); req.continueHandler(v -> { req.write(toSend); req.end(); }); req.sendHead(); })); await(); }
@Test public void testFollowRedirectSendHeadThenBody() throws Exception { Buffer expected = Buffer.buffer(TestUtils.randomAlphaString(2048)); AtomicBoolean redirected = new AtomicBoolean(); server.requestHandler(req -> { if (redirected.compareAndSet(false, true)) { assertEquals(HttpMethod.PUT, req.method()); req.bodyHandler(body -> { assertEquals(body, expected); req.response().setStatusCode(303).putHeader(HttpHeaders.LOCATION, "/whatever").end(); }); } else { assertEquals(HttpMethod.GET, req.method()); req.response().end(); } }); startServer(); HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(resp -> { assertEquals(200, resp.statusCode()); testComplete(); })).setFollowRedirects(true); req.putHeader("Content-Length", "" + expected.length()); req.exceptionHandler(this::fail); req.sendHead(v -> { req.end(expected); }); await(); }
private void testAccessNetSocketPendingResponseData(boolean pause) { server.requestHandler(req -> { NetSocket so = req.netSocket(); so.write("hello"); }); server.listen(onSuccess(s -> { HttpClientRequest req = client.request(HttpMethod.CONNECT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { NetSocket so = resp.netSocket(); assertNotNull(so); so.handler(buff -> { // With HTTP/1.1 the buffer is received immediately but delivered asynchronously assertEquals("hello", buff.toString()); testComplete(); }); if (pause) { so.pause(); vertx.setTimer(100, id -> { so.resume(); }); } })); req.sendHead(); })); await(); }
@Test public void test100ContinueHandledManually() throws Exception { server.close(); server = vertx.createHttpServer(createBaseServerOptions()); Buffer toSend = TestUtils.randomBuffer(1000); server.requestHandler(req -> { assertEquals("100-continue", req.getHeader("expect")); req.response().writeContinue(); req.bodyHandler(data -> { assertEquals(toSend, data); req.response().end(); }); }); server.listen(onSuccess(s -> { HttpClientRequest req = client.request(HttpMethod.PUT, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.endHandler(v -> testComplete()); })); req.headers().set("Expect", "100-continue"); req.setChunked(true); req.continueHandler(v -> { req.write(toSend); req.end(); }); req.sendHead(); })); await(); }
}); })); req.sendHead(version -> { assertSame(HttpVersion.HTTP_2, version); req.writeCustomFrame(10, 253, expectedSend);
@Test public void testUseRequestAfterComplete() { server.requestHandler(noOpHandler()); server.listen(onSuccess(server -> { HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); req.end(); Buffer buff = Buffer.buffer(); assertIllegalStateException(() -> req.end()); assertIllegalStateException(() -> req.continueHandler(noOpHandler())); assertIllegalStateException(() -> req.drainHandler(noOpHandler())); assertIllegalStateException(() -> req.end("foo")); assertIllegalStateException(() -> req.end(buff)); assertIllegalStateException(() -> req.end("foo", "UTF-8")); assertIllegalStateException(() -> req.sendHead()); assertIllegalStateException(() -> req.setChunked(false)); assertIllegalStateException(() -> req.setWriteQueueMaxSize(123)); assertIllegalStateException(() -> req.write(buff)); assertIllegalStateException(() -> req.write("foo")); assertIllegalStateException(() -> req.write("foo", "UTF-8")); assertIllegalStateException(() -> req.write(buff)); assertIllegalStateException(() -> req.writeQueueFull()); testComplete(); })); await(); }