@Test public void testClientExceptionHandlerCalledWhenServerTerminatesConnection() throws Exception { int numReqs = 10; CountDownLatch latch = new CountDownLatch(numReqs); server.requestHandler(request -> { request.response().close(); }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> { // Exception handler should be called for any requests in the pipeline if connection is closed for (int i = 0; i < numReqs; i++) { client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(err -> { latch.countDown(); })) .exceptionHandler(error -> fail("Exception handler should not be called")) .end(); } })); awaitLatch(latch); }
@Test public void testRequestTimeoutCanceledWhenRequestEndsNormally() { server.requestHandler(req -> req.response().end()); server.listen(onSuccess(s -> { AtomicReference<Throwable> exception = new AtomicReference<>(); // There is no server running, should fail to connect HttpClientRequest req = client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, noOpHandler()); req.exceptionHandler(exception::set); req.setTimeout(500); req.end(); vertx.setTimer(1000, id -> { assertNull("Did not expect any exception", exception.get()); testComplete(); }); })); await(); }
@Test public void testClientExceptionHandlerCalledWhenExceptionOnDataHandler() throws Exception { server.requestHandler(request -> { request.response().end("foo"); }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> { // Exception handler should be called for any exceptions in the data handler client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.handler(data -> { throw new RuntimeException("should be caught"); }); resp.exceptionHandler(t -> testComplete()); })).exceptionHandler(error -> fail()).end(); })); await(); }
@Test public void testClientExceptionHandlerCalledWhenExceptionOnBodyHandler() throws Exception { server.requestHandler(request -> { request.response().end("foo"); }).listen(DEFAULT_HTTP_PORT, onSuccess(s -> { // Exception handler should be called for any exceptions in the data handler client.request(HttpMethod.GET, DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { resp.bodyHandler(data -> { throw new RuntimeException("should be caught"); }); resp.exceptionHandler(t -> testComplete()); })).exceptionHandler(error -> fail()).end(); })); await(); }
@Test public void testFallbackOnHttp1() throws Exception { server.close(); server = vertx.createHttpServer(serverOptions.setUseAlpn(false)); server.requestHandler(req -> { assertEquals(HttpVersion.HTTP_1_1, req.version()); req.response().end(); }); startServer(); client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> { testComplete(); }).exceptionHandler(this::fail).end(); await(); }
private void testHttpProxyRequest2(Function<Handler<AsyncResult<HttpClientResponse>>, HttpClientRequest> reqFact) throws Exception { server.requestHandler(req -> { req.response().end(); }); server.listen(onSuccess(s -> { HttpClientRequest req = reqFact.apply(onSuccess(resp -> { assertEquals(200, resp.statusCode()); assertNotNull("request did not go through proxy", proxy.getLastUri()); assertEquals("Host header doesn't contain target host", "localhost:8080", proxy.getLastRequestHeaders().get("Host")); testComplete(); })); req.exceptionHandler(this::fail); req.end(); })); await(); }
@Test public void testOverrideAuthority() throws Exception { server.requestHandler(req -> { assertEquals("localhost:4444", req.host()); req.response().end(); }); startServer(); client.get(DEFAULT_HTTPS_PORT, DEFAULT_HTTPS_HOST, "/somepath", resp -> { testComplete(); }) .setHost("localhost:4444") .exceptionHandler(this::fail) .end(); await(); }
@Test public void testServerResponseWriteBufferFromOtherThread() throws Exception { server.requestHandler(req -> { runAsync(() -> { req.response().write("hello ").end("world"); }); }).listen(onSuccess(v -> { client.get(8080, "localhost", "/somepath", onSuccess(resp -> { assertEquals(200, resp.statusCode()); resp.bodyHandler(buff -> { assertEquals(Buffer.buffer("hello world"), buff); testComplete(); }); })).exceptionHandler(this::fail).end(); })); await(); }
@Test public void testConnectInvalidHost() { client.request(HttpMethod.GET, 9998, "255.255.255.255", DEFAULT_TEST_URI, onFailure(resp -> testComplete())) .exceptionHandler(t -> fail("Exception handler should not be called")) .end(); 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 testClientExceptionHandlerCalledWhenFailingToConnect() throws Exception { client.request(HttpMethod.GET, 9998, "255.255.255.255", DEFAULT_TEST_URI, onFailure(err -> testComplete())) .exceptionHandler(error -> fail("Exception handler should not be called")) .end(); await(); }
@Test public void testConnectInvalidPort() { client.request(HttpMethod.GET, 9998, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onFailure(err -> testComplete())) .exceptionHandler(t -> fail("Exception handler should not be called")) .end(); 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 testServerDoesNotSupportAlpn() throws Exception { waitFor(2); server.close(); server = vertx.createHttpServer(createBaseServerOptions().setUseAlpn(false)); server.requestHandler(req -> { assertEquals(HttpVersion.HTTP_1_1, req.version()); req.response().end(); complete(); }); startServer(); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { assertEquals(HttpVersion.HTTP_1_1, resp.version()); complete(); })).exceptionHandler(this::fail).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 testClientDoesNotSupportAlpn() throws Exception { waitFor(2); server.requestHandler(req -> { assertEquals(HttpVersion.HTTP_1_1, req.version()); req.response().end(); complete(); }); startServer(); client.close(); client = vertx.createHttpClient(createBaseClientOptions().setProtocolVersion(HttpVersion.HTTP_1_1).setUseAlpn(false)); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, onSuccess(resp -> { assertEquals(HttpVersion.HTTP_1_1, resp.version()); complete(); })).exceptionHandler(this::fail).end(); await(); }
@Test public void testInitialMaxConcurrentStreamZero() throws Exception { server.close(); server = vertx.createHttpServer(createBaseServerOptions().setInitialSettings(new Http2Settings().setMaxConcurrentStreams(0))); server.requestHandler(req -> { req.response().end(); }); server.connectionHandler(conn -> { vertx.setTimer(500, id -> { conn.updateSettings(new Http2Settings().setMaxConcurrentStreams(10)); }); }); startServer(); client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, DEFAULT_TEST_URI, resp -> { testComplete(); }).connectionHandler(conn -> { assertEquals(10, conn.remoteSettings().getMaxConcurrentStreams()); }).setTimeout(10000).exceptionHandler(this::fail).end(); await(); }
@Test public void testHttpSocksProxyRequest() throws Exception { startProxy(null, ProxyType.SOCKS5); client.close(); client = vertx.createHttpClient(new HttpClientOptions() .setProxyOptions(new ProxyOptions().setType(ProxyType.SOCKS5).setHost("localhost").setPort(proxy.getPort()))); server.requestHandler(req -> { req.response().end(); }); server.listen(onSuccess(s -> { client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onSuccess(resp -> { assertEquals(200, resp.statusCode()); assertNotNull("request did not go through proxy", proxy.getLastUri()); testComplete(); })).exceptionHandler(th -> fail(th)).end(); })); await(); }
@Test public void testHttpSocksProxyRequestAuth() throws Exception { startProxy("user", ProxyType.SOCKS5); client.close(); client = vertx.createHttpClient(new HttpClientOptions() .setProxyOptions(new ProxyOptions().setType(ProxyType.SOCKS5).setHost("localhost").setPort(proxy.getPort()) .setUsername("user").setPassword("user"))); server.requestHandler(req -> { req.response().end(); }); server.listen(onSuccess(s -> { client.get(DEFAULT_HTTP_PORT, DEFAULT_HTTP_HOST, "/", onSuccess(resp -> { assertEquals(200, resp.statusCode()); assertNotNull("request did not go through proxy", proxy.getLastUri()); testComplete(); })).exceptionHandler(th -> fail(th)).end(); })); 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(); }