@Override public void start() throws Exception { HttpClientRequest request = vertx.createHttpClient(new HttpClientOptions()).put(8080, "localhost", "/", resp -> { System.out.println("Got response " + resp.statusCode()); resp.bodyHandler(body -> System.out.println("Got data " + body.toString("ISO-8859-1"))); }); request.setChunked(true); for (int i = 0; i < 10; i++) { request.write("client-chunk-" + i); } request.end(); } }
@Test public void testSetChunkedToFalse() throws Exception { server.requestHandler(req -> req.response().setChunked(false).end()); startServer(); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", resp -> { testComplete(); }).setChunked(false).end(); 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 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 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 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 testRequestBodyWrite(boolean chunked) { Buffer body = Buffer.buffer(); server.requestHandler(req -> { req.bodyHandler(buffer -> { assertEquals(body, buffer); req.response().end(); }); }); server.listen(onSuccess(server -> { HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> testComplete()); int numWrites = 10; int chunkSize = 100; if (chunked) { req.setChunked(true); } else { req.headers().set("Content-Length", String.valueOf(numWrites * chunkSize)); } for (int i = 0; i < numWrites; i++) { Buffer b = TestUtils.randomBuffer(chunkSize); body.appendBuffer(b); req.write(b); } req.end(); })); 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 testRequestWrite() { int times = 3; Buffer chunk = TestUtils.randomBuffer(1000); server.requestHandler(req -> { req.bodyHandler(buff -> { Buffer expected = Buffer.buffer(); for (int i = 0;i < times;i++) { expected.appendBuffer(chunk); } assertEquals(expected, buff); testComplete(); }); }); server.listen(onSuccess(s -> { HttpClientRequest req = client.request(HttpMethod.POST, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); req.setChunked(true); int padding = 5; for (int i = 0;i < times;i++) { Buffer paddedChunk = TestUtils.leftPad(padding, chunk); assertEquals(paddedChunk.getByteBuf().readerIndex(), padding); req.write(paddedChunk); } req.end(); })); 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 testChunkedClientRequest() { server.requestHandler(req -> { HttpServerResponse resp = req.response(); assertEquals("chunked", req.getHeader("transfer-encoding")); req.bodyHandler(body -> { assertEquals("the-chunk", body.toString()); req.response().end(); }); }).listen(onSuccess(server -> { HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", res -> { testComplete(); }); req.setChunked(true); req.write("the-chunk"); vertx.setTimer(1, id -> { req.end(); }); })); await(); }
@Test public void testClientRequestExceptionHandlerCalledWhenExceptionOnDrainHandler() { pausingServer(resumeFuture -> { HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); req.setChunked(true); assertFalse(req.writeQueueFull()); req.setWriteQueueMaxSize(1000); Buffer buff = TestUtils.randomBuffer(10000); AtomicBoolean failed = new AtomicBoolean(); vertx.setPeriodic(1, id -> { req.write(buff); if (req.writeQueueFull()) { vertx.cancelTimer(id); req.drainHandler(v -> { throw new RuntimeException("error"); }) .exceptionHandler(t -> { // Called a second times when testComplete is called and close the http client if (failed.compareAndSet(false, true)) { testComplete(); } }); // Tell the server to resume resumeFuture.complete(); } }); }); 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 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(); }
@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 testClientDrainHandler() { pausingServer(resumeFuture -> { HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); req.setChunked(true); assertFalse(req.writeQueueFull()); req.setWriteQueueMaxSize(1000); Buffer buff = TestUtils.randomBuffer(10000); vertx.setPeriodic(1, id -> { req.write(buff); if (req.writeQueueFull()) { vertx.cancelTimer(id); req.drainHandler(v -> { assertFalse(req.writeQueueFull()); testComplete(); }); // Tell the server to resume resumeFuture.complete(); } }); }); await(); }
@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(); }