private void testURIAndPath(String uri, String path) { server.requestHandler(req -> { assertEquals(uri, req.uri()); assertEquals(path, req.path()); req.response().end(); }); server.listen(onSuccess(server -> { client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, uri, resp -> testComplete()).end(); })); await(); }
@Test public void testUseResponseAfterComplete() throws Exception { server.requestHandler(req -> { HttpServerResponse resp = req.response(); assertFalse(resp.ended()); resp.end(); assertTrue(resp.ended()); checkHttpServerResponse(resp); testComplete(); }); startServer(); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); await(); }
@Test public void testRequestTimeoutCanceledWhenRequestHasAnOtherError() { AtomicReference<Throwable> exception = new AtomicReference<>(); // There is no server running, should fail to connect client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(exception::set)) .setTimeout(800) .end(); vertx.setTimer(1500, id -> { assertNotNull("Expected an exception to be set", exception.get()); assertFalse("Expected to not end with timeout exception, but did: " + exception.get(), exception.get() instanceof TimeoutException); testComplete(); }); await(); }
@Test public void testClientConnectInvalidPort() { client.getNow(-1, "localhost", "/someuri", onFailure(err -> { assertEquals(err.getClass(), IllegalArgumentException.class); assertEquals(err.getMessage(), "port p must be in range 0 <= p <= 65535"); testComplete(); })); await(); }
@Test public void testListenTwice() throws Exception { server.requestHandler(noOpHandler()); server.listen(onSuccess(v -> testComplete())); assertIllegalStateException(() -> server.listen()); await(); }
@Test public void testServerActualPortWhenZero() { server = vertx.createHttpServer(createBaseServerOptions().setPort(0).setHost(DEFAULT_HTTP_HOST)); server .requestHandler(request -> { request.response().end("hello"); }) .listen(ar -> { assertTrue(ar.result().actualPort() != 0); vertx.createHttpClient(createBaseClientOptions()).getNow(ar.result().actualPort(), DEFAULT_HTTP_HOST, "/", onSuccess(response -> { assertEquals(response.statusCode(), 200); response.bodyHandler(body -> { assertEquals(body.toString("UTF-8"), "hello"); testComplete(); }); })); }); await(); }
@Test public void testServerConnectionHandler() throws Exception { AtomicInteger status = new AtomicInteger(); AtomicReference<HttpConnection> connRef = new AtomicReference<>(); server.connectionHandler(conn -> { assertEquals(0, status.getAndIncrement()); assertNull(connRef.getAndSet(conn)); }); server.requestHandler(req -> { assertEquals(1, status.getAndIncrement()); assertSame(connRef.get(), req.connection()); req.response().end(); }); CountDownLatch listenLatch = new CountDownLatch(1); server.listen(onSuccess(s -> listenLatch.countDown())); awaitLatch(listenLatch); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", resp -> { testComplete(); }); await(); }
assertEquals(HttpMethod.PUT, req.method()); req.bodyHandler(body -> { assertEquals(body, expected); String scheme = createBaseServerOptions().isSsl() ? "https" : "http"; req.response().setStatusCode(303).putHeader(HttpHeaders.LOCATION, scheme + "://localhost:8080/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) .setChunked(true) .write(buff1); awaitLatch(latch); req.end(buff2); await();
private void testDeliverPausedBufferWhenResume(Consumer<Runnable> scheduler) throws Exception { Buffer data = TestUtils.randomBuffer(2048); int num = 10; waitFor(num); List<CompletableFuture<Void>> resumes = Collections.synchronizedList(new ArrayList<>()); for (int i = 0;i < num;i++) { resp.setChunked(true).write(data); }); startServer(); client.close(); client = vertx.createHttpClient(createBaseClientOptions().setMaxPoolSize(1).setKeepAlive(true)); for (int i = 0;i < num;i++) { int idx = i; client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/" + i, onSuccess(resp -> { Buffer body = Buffer.buffer(); Thread t = Thread.currentThread(); resp.handler(buff -> { assertSame(t, Thread.currentThread()); resumes.get(idx).complete(null); body.appendBuffer(buff); resp.endHandler(v -> { complete(); }); resp.pause(); await();
@Test public void testClientExceptionHandlerCalledWhenServerTerminatesConnectionAfterPartialResponse() throws Exception { server.requestHandler(request -> { //Write partial response then close connection before completing it request.response().setChunked(true).write("foo").close(); }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> { // Exception handler should be called for any requests in the pipeline if connection is closed client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> resp.exceptionHandler(t -> testComplete()))).exceptionHandler(error -> fail()).end(); })); await(); }
@Test public void testServerResponseCloseHandlerNotHoldingLock() throws Exception { waitFor(7); server.requestHandler(req -> { HttpConnection conn = req.connection(); req.exceptionHandler(err -> { assertFalse(Thread.holdsLock(conn)); complete(); }); HttpServerResponse resp = req.response(); resp.exceptionHandler(err -> { assertFalse(Thread.holdsLock(conn)); complete(); }); resp.closeHandler(v -> { assertFalse(Thread.holdsLock(conn)); complete(); }); conn.closeHandler(err -> { assertFalse(Thread.holdsLock(conn)); complete(); }); resp.setChunked(true).write("hello"); }); startServer(); HttpClientRequest req = client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(resp -> { assertEquals(200, resp.statusCode()); HttpConnection conn = resp.request().connection(); resp.exceptionHandler(err -> { assertFalse(Thread.holdsLock(conn));
@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 testClientLocalAddress() throws Exception { String expectedAddress = TestUtils.loopbackAddress(); client.close(); client = vertx.createHttpClient(createBaseClientOptions().setLocalAddress(expectedAddress)); server.requestHandler(req -> { assertEquals(expectedAddress, req.remoteAddress().host()); req.response().end(); }); startServer(); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(resp -> { assertEquals(200, resp.statusCode()); testComplete(); })); await(); }
@Test public void testCloseHandlerWhenConnectionClose() throws Exception { server.requestHandler(req -> { HttpServerResponse resp = req.response(); resp.setChunked(true).write("some-data"); resp.closeHandler(v -> { checkHttpServerResponse(resp); testComplete(); }); }); startServer(); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/somepath", onSuccess(resp -> { resp.handler(v -> { resp.request().connection().close(); }); })); 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 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 testDisableIdleTimeoutInPool() throws Exception { server.requestHandler(req -> { req.response().end(); }); startServer(); client.close(); client = vertx.createHttpClient(createBaseClientOptions() .setIdleTimeout(1) .setMaxPoolSize(1) .setKeepAliveTimeout(10) ); client.getNow(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.endHandler(v1 -> { AtomicBoolean closed = new AtomicBoolean(); resp.request().connection().closeHandler(v2 -> { closed.set(true); }); vertx.setTimer(2000, id -> { assertFalse(closed.get()); testComplete(); }); }); })); await(); }
@Test public void testNotModifiedDoesNotSetAutomaticallySetContentLengthHeader() throws Exception { MultiMap respHeaders = checkEmptyHttpResponse(HttpMethod.GET, 304, MultiMap.caseInsensitiveMultiMap()); assertNull(respHeaders.get("content-length")); assertNull(respHeaders.get("transfer-encoding")); }
Buffer body = Buffer.buffer(); req.handler(buff -> { assertFalse(paused.get()); body.appendBuffer(buff); }); }); req.endHandler(v -> { assertEquals(expected, body); req.response().end(); }); }); startServer(); HttpClientRequest req = client.put(DEFAULT_HTTP_PORT, DEFAULT_HTTPS_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.endHandler(v -> { testComplete(); }); })).exceptionHandler(this::fail) await();
@Test public void testResetContentSetsContentLengthHeader() throws Exception { MultiMap respHeaders = checkEmptyHttpResponse(HttpMethod.GET, 205, MultiMap.caseInsensitiveMultiMap()); assertEquals("0", respHeaders.get("content-length")); assertNull(respHeaders.get("transfer-encoding")); }