diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyGracefulShutdown.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyGracefulShutdown.java index bb203a33d1..af1c7cfb5f 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyGracefulShutdown.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyGracefulShutdown.java @@ -17,13 +17,13 @@ package org.springframework.boot.web.embedded.jetty; import java.time.Duration; +import java.util.concurrent.ExecutionException; import java.util.function.Supplier; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; import org.springframework.boot.web.server.GracefulShutdown; @@ -55,7 +55,15 @@ class JettyGracefulShutdown implements GracefulShutdown { logger.info("Commencing graceful shutdown, allowing up to " + this.period.getSeconds() + "s for active requests to complete"); for (Connector connector : this.server.getConnectors()) { - ((ServerConnector) connector).setAccepting(false); + try { + connector.shutdown().get(); + } + catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + } + catch (ExecutionException ex) { + // Continue + } } this.shuttingDown = true; long end = System.currentTimeMillis() + this.period.toMillis(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java index 886eb0a95f..7bf3c53059 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactoryTests.java @@ -16,14 +16,12 @@ package org.springframework.boot.web.embedded.jetty; +import java.net.ConnectException; import java.net.InetAddress; import java.time.Duration; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Server; @@ -39,6 +37,7 @@ import org.springframework.http.client.reactive.JettyResourceFactory; import org.springframework.http.server.reactive.HttpHandler; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.inOrder; @@ -128,32 +127,18 @@ class JettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); + int port = this.webServer.getPort(); CountDownLatch responseLatch = new CountDownLatch(1); - getWebClient().build().get().retrieve().toBodilessEntity().subscribe((response) -> responseLatch.countDown()); + getWebClient(port).build().get().retrieve().toBodilessEntity() + .subscribe((response) -> responseLatch.countDown()); blockingHandler.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); - // We need to make two requests as Jetty accepts one additional request after a - // connector has been told to stop accepting requests - Mono> unconnectableRequest1 = getWebClient().build().get().retrieve().toBodilessEntity(); - Mono> unconnectableRequest2 = getWebClient().build().get().retrieve().toBodilessEntity(); + Mono> unconnectableRequest = getWebClient(port).build().get().retrieve() + .toBodilessEntity(); assertThat(shutdownResult.get()).isEqualTo(false); blockingHandler.completeOne(); - responseLatch.await(5, TimeUnit.SECONDS); - this.webServer.stop(); - List results = new ArrayList<>(); - try { - results.add(unconnectableRequest1.block()); - } - catch (Exception ex) { - results.add(ex); - } - try { - results.add(unconnectableRequest2.block()); - } - catch (Exception ex) { - results.add(ex); - } - assertThat(results).anySatisfy((result) -> assertThat(result).isInstanceOf(Exception.class)); + assertThatExceptionOfType(RuntimeException.class).isThrownBy(() -> unconnectableRequest.block()) + .withCauseInstanceOf(ConnectException.class); } @Override diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java index 033702b075..ffd26ad513 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactoryTests.java @@ -21,7 +21,7 @@ import java.time.Duration; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -30,8 +30,11 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletRegistration.Dynamic; +import org.apache.http.Header; import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; import org.apache.http.conn.HttpHostConnectException; +import org.apache.http.impl.client.HttpClients; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.Handler; import org.eclipse.jetty.server.Server; @@ -189,19 +192,80 @@ class JettyServletWebServerFactoryTests extends AbstractJettyServletWebServerFac registration.setAsyncSupported(true); }); this.webServer.start(); - Future request = initiateGetRequest("/blocking"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blocking"); blockingServlet.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); - // Jetty accepts one additional request after a connector has been told to stop - // accepting requests - Future unconnectableRequest1 = initiateGetRequest("/"); - Future unconnectableRequest2 = initiateGetRequest("/"); + Future unconnectableRequest = initiateGetRequest(port, "/"); assertThat(shutdownResult.get()).isEqualTo(false); blockingServlet.admitOne(); - assertThat(request.get()).isInstanceOf(HttpResponse.class); + Object response = request.get(); + assertThat(response).isInstanceOf(HttpResponse.class); + assertThat(unconnectableRequest.get()).isInstanceOf(HttpHostConnectException.class); this.webServer.stop(); - List results = Arrays.asList(unconnectableRequest1.get(), unconnectableRequest2.get()); - assertThat(results).anySatisfy((result) -> assertThat(result).isInstanceOf(HttpHostConnectException.class)); + } + + @Test + void whenServerIsShuttingDownGracefullyThenResponseToRequestOnIdleConnectionWillHaveAConnectionCloseHeader() + throws Exception { + AbstractServletWebServerFactory factory = getFactory(); + Shutdown shutdown = new Shutdown(); + shutdown.setGracePeriod(Duration.ofSeconds(5)); + factory.setShutdown(shutdown); + BlockingServlet blockingServlet = new BlockingServlet(); + this.webServer = factory.getWebServer((context) -> { + Dynamic registration = context.addServlet("blockingServlet", blockingServlet); + registration.addMapping("/blocking"); + registration.setAsyncSupported(true); + }); + this.webServer.start(); + int port = this.webServer.getPort(); + HttpClient client = HttpClients.createMinimal(); + Future request = initiateGetRequest(client, port, "/blocking"); + blockingServlet.awaitQueue(); + blockingServlet.admitOne(); + Object response = request.get(); + assertThat(response).isInstanceOf(HttpResponse.class); + assertThat(((HttpResponse) response).getStatusLine().getStatusCode()).isEqualTo(200); + assertThat(((HttpResponse) response).getFirstHeader("Connection")).isNull(); + this.webServer.shutDownGracefully(); + request = initiateGetRequest(client, port, "/blocking"); + blockingServlet.awaitQueue(); + blockingServlet.admitOne(); + response = request.get(); + assertThat(response).isInstanceOf(HttpResponse.class); + assertThat(((HttpResponse) response).getStatusLine().getStatusCode()).isEqualTo(200); + assertThat(((HttpResponse) response).getFirstHeader("Connection")).isNotNull().extracting(Header::getValue) + .isEqualTo("close"); + this.webServer.stop(); + } + + @Test + void whenARequestCompletesAfterGracefulShutdownHasBegunThenItHasAConnectionCloseHeader() + throws InterruptedException, ExecutionException { + AbstractServletWebServerFactory factory = getFactory(); + Shutdown shutdown = new Shutdown(); + shutdown.setGracePeriod(Duration.ofSeconds(30)); + factory.setShutdown(shutdown); + BlockingServlet blockingServlet = new BlockingServlet(); + this.webServer = factory.getWebServer((context) -> { + Dynamic registration = context.addServlet("blockingServlet", blockingServlet); + registration.addMapping("/blocking"); + registration.setAsyncSupported(true); + }); + this.webServer.start(); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blocking"); + blockingServlet.awaitQueue(); + long start = System.currentTimeMillis(); + Future shutdownResult = initiateGracefulShutdown(); + blockingServlet.admitOne(); + assertThat(shutdownResult.get()).isTrue(); + long end = System.currentTimeMillis(); + assertThat(end - start).isLessThanOrEqualTo(30000); + Object requestResult = request.get(); + assertThat(requestResult).isInstanceOf(HttpResponse.class); + assertThat(((HttpResponse) requestResult).getFirstHeader("Connection").getValue()).isEqualTo("close"); } private Ssl getSslSettings(String... enabledProtocols) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java index 7180a29a07..06c1dead36 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/netty/NettyReactiveWebServerFactoryTests.java @@ -112,7 +112,7 @@ class NettyReactiveWebServerFactoryTests extends AbstractReactiveWebServerFactor BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); - WebClient webClient = getWebClient().build(); + WebClient webClient = getWebClient(this.webServer.getPort()).build(); webClient.get().retrieve().toBodilessEntity().subscribe(); blockingHandler.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java index 5b452e8d5a..8c7eeaaf02 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatReactiveWebServerFactoryTests.java @@ -271,7 +271,7 @@ class TomcatReactiveWebServerFactoryTests extends AbstractReactiveWebServerFacto BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); - WebClient webClient = getWebClient().build(); + WebClient webClient = getWebClient(this.webServer.getPort()).build(); webClient.get().retrieve().toBodilessEntity().subscribe(); blockingHandler.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java index 6c27655eb1..5a5c11e396 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java @@ -574,10 +574,11 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory registration.setAsyncSupported(true); }); this.webServer.start(); - Future request = initiateGetRequest("/blocking"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blocking"); blockingServlet.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); - Future unconnectableRequest = initiateGetRequest("/"); + Future unconnectableRequest = initiateGetRequest(port, "/"); assertThat(shutdownResult.get()).isEqualTo(false); blockingServlet.admitOne(); assertThat(request.get()).isInstanceOf(HttpResponse.class); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java index 465aa6fe2f..86ad899b16 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowReactiveWebServerFactoryTests.java @@ -118,7 +118,7 @@ class UndertowReactiveWebServerFactoryTests extends AbstractReactiveWebServerFac BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); - WebClient webClient = getWebClient().build(); + WebClient webClient = getWebClient(this.webServer.getPort()).build(); webClient.get().retrieve().toBodilessEntity().subscribe(); blockingHandler.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); @@ -146,7 +146,7 @@ class UndertowReactiveWebServerFactoryTests extends AbstractReactiveWebServerFac assertThat(accessLogDirectory.listFiles()).isEmpty(); this.webServer = factory.getWebServer(new EchoHandler()); this.webServer.start(); - WebClient client = getWebClient().build(); + WebClient client = getWebClient(this.webServer.getPort()).build(); Mono result = client.post().uri("/test").contentType(MediaType.TEXT_PLAIN) .body(BodyInserters.fromValue("Hello World")).exchange() .flatMap((response) -> response.bodyToMono(String.class)); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java index 298562a719..3952436ad5 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java @@ -190,10 +190,11 @@ class UndertowServletWebServerFactoryTests extends AbstractServletWebServerFacto registration.setAsyncSupported(true); }); this.webServer.start(); - Future request = initiateGetRequest("/blocking"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blocking"); blockingServlet.awaitQueue(); Future shutdownResult = initiateGracefulShutdown(); - Future rejectedRequest = initiateGetRequest("/"); + Future rejectedRequest = initiateGetRequest(port, "/"); assertThat(shutdownResult.get()).isEqualTo(false); blockingServlet.admitOne(); assertThat(request.get()).isInstanceOf(HttpResponse.class); diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java index a574226ed8..d77f79384c 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java @@ -109,8 +109,8 @@ public abstract class AbstractReactiveWebServerFactoryTests { this.webServer.start(); return port; }); - Mono result = getWebClient().build().post().uri("/test").contentType(MediaType.TEXT_PLAIN) - .body(BodyInserters.fromValue("Hello World")).exchange() + Mono result = getWebClient(this.webServer.getPort()).build().post().uri("/test") + .contentType(MediaType.TEXT_PLAIN).body(BodyInserters.fromValue("Hello World")).exchange() .flatMap((response) -> response.bodyToMono(String.class)); assertThat(result.block(Duration.ofSeconds(30))).isEqualTo("Hello World"); assertThat(this.webServer.getPort()).isEqualTo(specificPort); @@ -269,12 +269,12 @@ public abstract class AbstractReactiveWebServerFactoryTests { StepVerifier.create(result).expectError(SSLException.class).verify(Duration.ofSeconds(10)); } - protected WebClient.Builder getWebClient() { - return getWebClient(HttpClient.create().wiretap(true)); + protected WebClient.Builder getWebClient(int port) { + return getWebClient(HttpClient.create().wiretap(true), port); } - protected WebClient.Builder getWebClient(HttpClient client) { - InetSocketAddress address = new InetSocketAddress(this.webServer.getPort()); + protected WebClient.Builder getWebClient(HttpClient client, int port) { + InetSocketAddress address = new InetSocketAddress(port); String baseUrl = "http://" + address.getHostString() + ":" + address.getPort(); return WebClient.builder().clientConnector(new ReactorClientHttpConnector(client)).baseUrl(baseUrl); } @@ -368,7 +368,8 @@ public abstract class AbstractReactiveWebServerFactoryTests { BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); - Mono> request = getWebClient().build().get().retrieve().toBodilessEntity(); + Mono> request = getWebClient(this.webServer.getPort()).build().get().retrieve() + .toBodilessEntity(); AtomicReference> responseReference = new AtomicReference<>(); CountDownLatch responseLatch = new CountDownLatch(1); request.subscribe((response) -> { @@ -399,7 +400,8 @@ public abstract class AbstractReactiveWebServerFactoryTests { BlockingHandler blockingHandler = new BlockingHandler(); this.webServer = factory.getWebServer(blockingHandler); this.webServer.start(); - Mono> request = getWebClient().build().get().retrieve().toBodilessEntity(); + Mono> request = getWebClient(this.webServer.getPort()).build().get().retrieve() + .toBodilessEntity(); AtomicReference> responseReference = new AtomicReference<>(); CountDownLatch responseLatch = new CountDownLatch(1); request.subscribe((response) -> { @@ -437,7 +439,7 @@ public abstract class AbstractReactiveWebServerFactoryTests { .tcpConfiguration((tcpClient) -> tcpClient.doOnConnected( (connection) -> connection.channel().pipeline().addBefore(NettyPipeline.HttpDecompressor, "CompressionTest", new CompressionDetectionHandler()))); - return getWebClient(client).build(); + return getWebClient(client, this.webServer.getPort()).build(); } protected void assertResponseIsCompressed(ResponseEntity response) { @@ -451,8 +453,8 @@ public abstract class AbstractReactiveWebServerFactoryTests { protected void assertForwardHeaderIsUsed(AbstractReactiveWebServerFactory factory) { this.webServer = factory.getWebServer(new XForwardedHandler()); this.webServer.start(); - String body = getWebClient().build().get().header("X-Forwarded-Proto", "https").retrieve() - .bodyToMono(String.class).block(Duration.ofSeconds(30)); + String body = getWebClient(this.webServer.getPort()).build().get().header("X-Forwarded-Proto", "https") + .retrieve().bodyToMono(String.class).block(Duration.ofSeconds(30)); assertThat(body).isEqualTo("https"); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java index a78be6e166..6a493abde5 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java @@ -1041,7 +1041,8 @@ public abstract class AbstractServletWebServerFactoryTests { registration.addMapping("/blocking"); }); this.webServer.start(); - Future request = initiateGetRequest("/blocking"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blocking"); blockingServlet.awaitQueue(); long start = System.currentTimeMillis(); assertThat(this.webServer.shutDownGracefully()).isFalse(); @@ -1066,7 +1067,8 @@ public abstract class AbstractServletWebServerFactoryTests { registration.setAsyncSupported(true); }); this.webServer.start(); - Future request = initiateGetRequest("/blocking"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blocking"); blockingServlet.awaitQueue(); long start = System.currentTimeMillis(); Future shutdownResult = initiateGracefulShutdown(); @@ -1090,7 +1092,8 @@ public abstract class AbstractServletWebServerFactoryTests { registration.setAsyncSupported(true); }); this.webServer.start(); - Future request = initiateGetRequest("/blockingAsync"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blockingAsync"); blockingAsyncServlet.awaitQueue(); long start = System.currentTimeMillis(); assertThat(this.webServer.shutDownGracefully()).isFalse(); @@ -1115,7 +1118,8 @@ public abstract class AbstractServletWebServerFactoryTests { registration.setAsyncSupported(true); }); this.webServer.start(); - Future request = initiateGetRequest("/blockingAsync"); + int port = this.webServer.getPort(); + Future request = initiateGetRequest(port, "/blockingAsync"); blockingAsyncServlet.awaitQueue(); long start = System.currentTimeMillis(); Future shutdownResult = initiateGracefulShutdown(); @@ -1133,15 +1137,14 @@ public abstract class AbstractServletWebServerFactoryTests { return future; } - protected Future initiateGetRequest(String path) { - return initiateGetRequest(HttpClients.createDefault(), path); + protected Future initiateGetRequest(int port, String path) { + return initiateGetRequest(HttpClients.createMinimal(), port, path); } - protected Future initiateGetRequest(HttpClient httpClient, String path) { + protected Future initiateGetRequest(HttpClient httpClient, int port, String path) { RunnableFuture getRequest = new FutureTask<>(() -> { try { - HttpResponse response = httpClient - .execute(new HttpGet("http://localhost:" + this.webServer.getPort() + path)); + HttpResponse response = httpClient.execute(new HttpGet("http://localhost:" + port + path)); response.getEntity().getContent().close(); return response; }