diff --git a/components/api/src/main/java/com/hotels/styx/api/FullHttpRequest.java b/components/api/src/main/java/com/hotels/styx/api/FullHttpRequest.java index 2fdf4c2366..806913cc4d 100644 --- a/components/api/src/main/java/com/hotels/styx/api/FullHttpRequest.java +++ b/components/api/src/main/java/com/hotels/styx/api/FullHttpRequest.java @@ -309,6 +309,7 @@ public Builder newBuilder() { */ public HttpRequest toStreamingRequest() { HttpRequest.Builder streamingBuilder = new HttpRequest.Builder(this) + .disableValidation() .clientAddress(clientAddress); if (this.body.length == 0) { diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java index 8fe22bad1d..bd77e3c1e9 100644 --- a/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java +++ b/components/api/src/main/java/com/hotels/styx/api/HttpResponse.java @@ -163,6 +163,7 @@ public StyxObservable toFullResponse(int maxContentBytes) { }) .map(HttpResponse::decodeAndRelease) .map(decoded -> new FullHttpResponse.Builder(this, decoded) + .disableValidation() .build()); return new StyxCoreObservable<>(delegate); diff --git a/components/api/src/main/java/com/hotels/styx/api/client/UrlConnectionHttpClient.java b/components/api/src/main/java/com/hotels/styx/api/client/UrlConnectionHttpClient.java deleted file mode 100644 index 9f03056a46..0000000000 --- a/components/api/src/main/java/com/hotels/styx/api/client/UrlConnectionHttpClient.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - Copyright (C) 2013-2018 Expedia Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ -package com.hotels.styx.api.client; - -import com.google.common.base.Throwables; -import com.hotels.styx.api.FullHttpResponse; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpHeader; -import com.hotels.styx.api.HttpRequest; -import com.hotels.styx.api.HttpResponse; -import rx.Observable; - -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Objects; -import java.util.Optional; - -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.base.Strings.isNullOrEmpty; -import static com.google.common.io.ByteStreams.toByteArray; -import static com.hotels.styx.api.common.Joiners.JOINER_ON_COMMA; - -/** - * An Implementation of HttpClient that uses the java sun URL connection object. - *

- * todo should be moved out of api - */ -public class UrlConnectionHttpClient implements HttpClient { - private static final X509TrustManager TRUST_ALL = new X509TrustManager() { - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) - throws CertificateException { - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return null; - } - }; - - private final int connectTimeoutMillis; - private final int readTimeoutMillis; - private final SSLSocketFactory sslSocketFactory; - - /** - * Constructs a new client. - * - * @param connectTimeoutMillis socket connection timeout in milliseconds - * @param readTimeoutMillis socket read/write timeout in milliseconds - */ - public UrlConnectionHttpClient(int connectTimeoutMillis, int readTimeoutMillis) { - this(connectTimeoutMillis, readTimeoutMillis, sslSocketFactory("TLS")); - } - - /** - * Constructs a new client. - * - * @param connectTimeoutMillis socket connection timeout in milliseconds - * @param readTimeoutMillis socket read/write timeout in milliseconds - * @param protocol supported TLS protocol, TLSv1.1, TLSv1.2, etc. - */ - public UrlConnectionHttpClient(int connectTimeoutMillis, int readTimeoutMillis, String protocol) { - this(connectTimeoutMillis, readTimeoutMillis, sslSocketFactory(protocol)); - } - - private UrlConnectionHttpClient(int connectTimeoutMillis, int readTimeoutMillis, SSLSocketFactory sslSocketFactory) { - this.connectTimeoutMillis = connectTimeoutMillis; - this.readTimeoutMillis = readTimeoutMillis; - this.sslSocketFactory = checkNotNull(sslSocketFactory); - } - - private static SSLSocketFactory sslSocketFactory(String protocol) { - try { - SSLContext context = SSLContext.getInstance(protocol); - context.init(null, new TrustManager[]{TRUST_ALL}, new SecureRandom()); - return context.getSocketFactory(); - } catch (KeyManagementException | NoSuchAlgorithmException e) { - throw Throwables.propagate(e); - } - } - - @Override - public Observable sendRequest(HttpRequest request) { - try { - HttpURLConnection connection = openConnection(request); - prepareRequest(connection, request); - return Observable.just(readResponse(connection)); - } catch (IOException e) { - return Observable.error(e); - } - } - - private HttpURLConnection openConnection(HttpRequest request) throws IOException { - URL url = request.url().toURL(); - URLConnection urlConnection = url.openConnection(); - HttpURLConnection connection = "https".equals(url.getProtocol()) - ? httpsURLConnection((HttpsURLConnection) urlConnection) - : (HttpURLConnection) urlConnection; - connection.setConnectTimeout(this.connectTimeoutMillis); - connection.setReadTimeout(this.readTimeoutMillis); - return connection; - } - - private HttpsURLConnection httpsURLConnection(HttpsURLConnection urlConnection) { - urlConnection.setSSLSocketFactory(sslSocketFactory); - return urlConnection; - } - - private void prepareRequest(HttpURLConnection connection, HttpRequest request) throws IOException { - connection.setRequestMethod(request.method().name()); - connection.setRequestProperty("Connection", "close"); - connection.setDoInput(true); - for (HttpHeader httpHeader : request.headers()) { - connection.addRequestProperty(httpHeader.name(), httpHeader.value()); - } - } - - private HttpResponse readResponse(HttpURLConnection connection) throws IOException { - int status = connection.getResponseCode(); - FullHttpResponse.Builder response = FullHttpResponse.response(com.hotels.styx.api.messages.HttpResponseStatus.statusWithCode(status)); - - try (InputStream stream = getInputStream(connection, status)) { - byte[] content = toByteArray(stream); - if (content.length > 0) { - response.body(content, true); - } - connection.getHeaderFields().forEach((key, value) -> { - if (!isNullOrEmpty(key)) { - response.header(key, JOINER_ON_COMMA.join(value)); - } - }); - } - - return response.build().toStreamingResponse(); - } - - private static InputStream getInputStream(HttpURLConnection connection, int status) throws IOException { - if (status >= 400) { - return Optional.ofNullable(connection.getErrorStream()) - .orElseGet(EmptyInputStream::new); - } - - return connection.getInputStream(); - } - - private static class EmptyInputStream extends InputStream { - @Override - public int read() throws IOException { - return -1; - } - } - - @Override - public int hashCode() { - return Objects.hash(this.connectTimeoutMillis, this.readTimeoutMillis); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - UrlConnectionHttpClient other = (UrlConnectionHttpClient) obj; - return Objects.equals(this.connectTimeoutMillis, other.connectTimeoutMillis) && Objects.equals(this.readTimeoutMillis, other.readTimeoutMillis); - } -} diff --git a/components/client/src/main/java/com/hotels/styx/api/FullHttpClient.java b/components/client/src/main/java/com/hotels/styx/api/FullHttpClient.java new file mode 100644 index 0000000000..159cae4fb9 --- /dev/null +++ b/components/client/src/main/java/com/hotels/styx/api/FullHttpClient.java @@ -0,0 +1,35 @@ +/* + Copyright (C) 2013-2018 Expedia Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +package com.hotels.styx.api; + +import java.util.concurrent.CompletableFuture; + +/** + * HTTP Client that returns an observable of response. + */ +public interface FullHttpClient { + /** + * Processes a new request. + * + * @param request HTTP request to process + * @return an observable of HTTP sendRequest. + * + * The sendRequest will be sent when the returned observable is subscribed to. + * In order to cancel the ongoing request, just unsubscribe from it. + * + */ + CompletableFuture sendRequest(FullHttpRequest request); +} diff --git a/components/api/src/main/java/com/hotels/styx/api/HttpClient.java b/components/client/src/main/java/com/hotels/styx/api/HttpClient.java similarity index 100% rename from components/api/src/main/java/com/hotels/styx/api/HttpClient.java rename to components/client/src/main/java/com/hotels/styx/api/HttpClient.java diff --git a/components/client/src/main/java/com/hotels/styx/client/SimpleHttpClient.java b/components/client/src/main/java/com/hotels/styx/client/SimpleHttpClient.java new file mode 100644 index 0000000000..7524d27e06 --- /dev/null +++ b/components/client/src/main/java/com/hotels/styx/client/SimpleHttpClient.java @@ -0,0 +1,171 @@ +/* + Copyright (C) 2013-2018 Expedia Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ +package com.hotels.styx.client; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.net.HostAndPort; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpRequest; +import com.hotels.styx.api.FullHttpResponse; +import com.hotels.styx.api.Url; +import com.hotels.styx.api.client.Connection; +import com.hotels.styx.api.client.Origin; +import com.hotels.styx.api.service.TlsSettings; +import com.hotels.styx.client.netty.connectionpool.HttpRequestOperation; +import com.hotels.styx.client.netty.connectionpool.NettyConnectionFactory; +import rx.Observable; + +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.hotels.styx.api.HttpHeaderNames.HOST; +import static com.hotels.styx.api.HttpHeaderNames.USER_AGENT; +import static com.hotels.styx.api.StyxInternalObservables.toRxObservable; +import static com.hotels.styx.api.client.Origin.newOriginBuilder; +import static com.hotels.styx.client.HttpConfig.newHttpConfigBuilder; +import static com.hotels.styx.common.CompletableFutures.fromSingleObservable; + +/** + * A client that uses netty as transport. + */ +public final class SimpleHttpClient implements FullHttpClient { + private final Optional userAgent; + private final ConnectionSettings connectionSettings; + private final int maxResponseSize; + private final Connection.Factory connectionFactory; + + private SimpleHttpClient(Builder builder) { + this.userAgent = Optional.ofNullable(builder.userAgent); + this.connectionSettings = builder.connectionSettings; + this.maxResponseSize = builder.maxResponseSize; + this.connectionFactory = builder.connectionFactory; + } + + public CompletableFuture sendRequest(FullHttpRequest request) { + FullHttpRequest networkRequest = addUserAgent(request); + Origin origin = originFromRequest(networkRequest); + + Observable responseObservable = connectionFactory.createConnection(origin, connectionSettings) + .flatMap(connection -> connection.write(networkRequest.toStreamingRequest()) + .flatMap(response -> toRxObservable(response.toFullResponse(maxResponseSize))) + .doOnTerminate(connection::close)); + + return fromSingleObservable(responseObservable); + } + + private FullHttpRequest addUserAgent(FullHttpRequest request) { + return Optional.of(request) + .filter(req -> !req.header(USER_AGENT).isPresent()) + .flatMap(req -> userAgent.map(userAgent -> request.newBuilder() + .addHeader(USER_AGENT, userAgent) + .build())) + .orElse(request); + } + + private static Origin originFromRequest(FullHttpRequest request) { + String hostAndPort = request.header(HOST) + .orElseGet(() -> { + checkArgument(request.url().isAbsolute(), "host header is not set for request=%s", request); + return request.url().authority().map(Url.Authority::hostAndPort) + .orElseThrow(() -> new IllegalArgumentException("Cannot send request " + request + " as URL is not absolute and no HOST header is present")); + }); + + return newOriginBuilder(HostAndPort.fromString(hostAndPort)).build(); + } + + /** + * Builder for {@link SimpleHttpClient}. + */ + public static class Builder { + private Connection.Factory connectionFactory; + private TlsSettings tlsSettings; + private String userAgent; + private ConnectionSettings connectionSettings = new ConnectionSettings(1000); + private int responseTimeout = 60000; + private int maxResponseSize = 1024 * 100; + private int maxHeaderSize = 8192; + private String threadName = "simple-netty-http-client"; + + public Builder connectionSettings(ConnectionSettings connectionSettings) { + this.connectionSettings = connectionSettings; + return this; + } + + /** + * Sets the user-agent header value to be included in requests. + * + * @param userAgent user-agent + * @return this builder + */ + public Builder userAgent(String userAgent) { + this.userAgent = userAgent; + return this; + } + + public Builder responseTimeoutMillis(int responseTimeout) { + this.responseTimeout = responseTimeout; + return this; + } + + public Builder maxResponseSize(int maxResponseSize) { + this.maxResponseSize = maxResponseSize; + return this; + } + + public Builder tlsSettings(TlsSettings tlsSettings) { + this.tlsSettings = tlsSettings; + return this; + } + + public Builder maxHeaderSize(int maxHeaderSize) { + this.maxHeaderSize = maxHeaderSize; + return this; + } + + public Builder threadName(String threadName) { + this.threadName = threadName; + return this; + } + + @VisibleForTesting + Builder setConnectionFactory(Connection.Factory connectionFactory) { + this.connectionFactory = connectionFactory; + return this; + } + + /** + * Construct a client instance. + * + * @return a new instance + */ + public SimpleHttpClient build() { + connectionFactory = connectionFactory != null ? connectionFactory : new NettyConnectionFactory.Builder() + .name(threadName) + .httpConfig(newHttpConfigBuilder().setMaxHeadersSize(maxHeaderSize).build()) + .tlsSettings(tlsSettings) + .httpRequestOperationFactory(request -> new HttpRequestOperation( + request, + null, + false, + responseTimeout, + false, + false)) + .build(); + return new SimpleHttpClient(this); + } + } +} diff --git a/components/client/src/main/java/com/hotels/styx/client/SimpleNettyHttpClient.java b/components/client/src/main/java/com/hotels/styx/client/SimpleNettyHttpClient.java deleted file mode 100644 index 0c31ab716c..0000000000 --- a/components/client/src/main/java/com/hotels/styx/client/SimpleNettyHttpClient.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - Copyright (C) 2013-2018 Expedia Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ -package com.hotels.styx.client; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.net.HostAndPort; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpRequest; -import com.hotels.styx.api.HttpResponse; -import com.hotels.styx.api.Url; -import com.hotels.styx.api.client.ConnectionDestination; -import com.hotels.styx.api.client.Origin; -import rx.Observable; - -import java.util.Optional; -import java.util.concurrent.ExecutionException; -import java.util.function.Function; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Throwables.propagate; -import static com.hotels.styx.api.HttpHeaderNames.HOST; -import static com.hotels.styx.api.HttpHeaderNames.USER_AGENT; -import static com.hotels.styx.api.client.Origin.newOriginBuilder; -import static java.util.Objects.requireNonNull; - -/** - * A client that uses netty as transport. - */ -public final class SimpleNettyHttpClient implements HttpClient { - private final LoadingCache connectionDestinationByOrigin; - private final Optional userAgent; - - private SimpleNettyHttpClient(Builder builder) { - ConnectionDestination.Factory connectionDestinationFactory = requireNonNull(builder.connectionDestinationFactory); - - this.userAgent = Optional.ofNullable(builder.userAgent); - this.connectionDestinationByOrigin = CacheBuilder.newBuilder().build(cacheLoader(connectionDestinationFactory::create)); - } - - @Override - public Observable sendRequest(HttpRequest request) { - HttpRequest networkRequest = addUserAgent(request); - Origin origin = originFromRequest(networkRequest); - ConnectionDestination connectionDestination = connectionDestination(origin); - Observable response = connectionDestination.withConnection(connection -> connection.write(networkRequest)); - return new HttpTransaction.NonCancellableHttpTransaction(response).response(); - } - - private HttpRequest addUserAgent(HttpRequest request) { - return Optional.of(request) - .filter(req -> !req.header(USER_AGENT).isPresent()) - .flatMap(req -> userAgent.map(userAgent -> addUserAgent(request, userAgent))) - .orElse(request); - } - - private static HttpRequest addUserAgent(HttpRequest request, String userAgent) { - return request.newBuilder() - .addHeader(USER_AGENT, userAgent) - .build(); - } - - private ConnectionDestination connectionDestination(Origin origin) { - try { - return connectionDestinationByOrigin.get(origin); - } catch (ExecutionException e) { - throw propagate(e.getCause()); - } - } - - private static Origin originFromRequest(HttpRequest request) { - String hostAndPort = request.header(HOST) - .orElseGet(() -> { - checkArgument(request.url().isAbsolute(), "host header is not set for request=%s", request); - return request.url().authority().map(Url.Authority::hostAndPort) - .orElseThrow(() -> new IllegalArgumentException("Cannot send request " + request + " as URL is not absolute and no HOST header is present")); - }); - - return newOriginBuilder(HostAndPort.fromString(hostAndPort)).build(); - } - - // Annoyingly, Guava's CacheLoader is an abstract class, which cannot be a lambda/method reference. - // This is a workaround for that. - private static CacheLoader cacheLoader(Function loader) { - return new CacheLoader() { - @Override - public C load(O key) throws Exception { - return loader.apply(key); - } - }; - } - - /** - * Builder for {@link SimpleNettyHttpClient}. - */ - public static class Builder { - private String userAgent; - private ConnectionDestination.Factory connectionDestinationFactory; - - /** - * Sets the factory that will produce connection-destination objects for origins. - * - * @param connectionDestinationFactory factory - * @return this builder - */ - public Builder connectionDestinationFactory(ConnectionDestination.Factory connectionDestinationFactory) { - this.connectionDestinationFactory = connectionDestinationFactory; - return this; - } - - /** - * Sets the user-agent header value to be included in requests. - * - * @param userAgent user-agent - * @return this builder - */ - public Builder userAgent(String userAgent) { - this.userAgent = userAgent; - return this; - } - - /** - * Construct a client instance. - * - * @return a new instance - */ - public HttpClient build() { - return new SimpleNettyHttpClient(this); - } - } -} diff --git a/components/client/src/main/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheck.java b/components/client/src/main/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheck.java index 21f61421c1..88e22e8a2d 100644 --- a/components/client/src/main/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheck.java +++ b/components/client/src/main/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheck.java @@ -16,8 +16,8 @@ package com.hotels.styx.client.healthcheck; import com.codahale.metrics.Meter; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpRequest; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpRequest; import com.hotels.styx.api.client.Origin; import com.hotels.styx.api.metrics.MetricRegistry; import com.hotels.styx.common.SimpleCache; @@ -26,7 +26,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.hotels.styx.api.HttpHeaderNames.HOST; -import static com.hotels.styx.api.StyxInternalObservables.toRxObservable; import static com.hotels.styx.api.messages.HttpResponseStatus.OK; import static com.hotels.styx.client.healthcheck.OriginHealthCheckFunction.OriginState.HEALTHY; import static com.hotels.styx.client.healthcheck.OriginHealthCheckFunction.OriginState.UNHEALTHY; @@ -36,10 +35,8 @@ * Health-check that works by making a request to a URL and ensuring that it gets an HTTP 200 OK code back. */ public class UrlRequestHealthCheck implements OriginHealthCheckFunction { - private static final Observer RELEASE_BUFFER = new DoNothingObserver(); - private final String healthCheckUri; - private final HttpClient client; + private final FullHttpClient client; private final SimpleCache meterCache; /** @@ -49,7 +46,7 @@ public class UrlRequestHealthCheck implements OriginHealthCheckFunction { * @param client HTTP client to make health-check requests with * @param metricRegistry metric registry */ - public UrlRequestHealthCheck(String healthCheckUri, HttpClient client, MetricRegistry metricRegistry) { + public UrlRequestHealthCheck(String healthCheckUri, FullHttpClient client, MetricRegistry metricRegistry) { this.healthCheckUri = uriWithInitialSlash(healthCheckUri); this.client = checkNotNull(client); this.meterCache = new SimpleCache<>(origin -> metricRegistry.meter("origins.healthcheck.failure." + origin.applicationId())); @@ -61,26 +58,27 @@ private static String uriWithInitialSlash(String uri) { @Override public void check(Origin origin, OriginHealthCheckFunction.Callback responseCallback) { - HttpRequest request = newHealthCheckRequestFor(origin); + FullHttpRequest request = newHealthCheckRequestFor(origin); client.sendRequest(request) - .flatMap(response -> toRxObservable(response.toFullResponse(1024 * 100))) - .subscribe(response -> { - if (response.status().equals(OK)) { - responseCallback.originStateResponse(HEALTHY); - } else { + .handle((response, cause) -> { + if (response != null) { + if (response.status().equals(OK)) { + responseCallback.originStateResponse(HEALTHY); + } else { + meterCache.get(origin).mark(); + responseCallback.originStateResponse(UNHEALTHY); + } + } else if (cause != null) { meterCache.get(origin).mark(); responseCallback.originStateResponse(UNHEALTHY); } - - }, error -> { - meterCache.get(origin).mark(); - responseCallback.originStateResponse(UNHEALTHY); + return null; }); } - private HttpRequest newHealthCheckRequestFor(Origin origin) { - return HttpRequest.get(healthCheckUri) + private FullHttpRequest newHealthCheckRequestFor(Origin origin) { + return FullHttpRequest.get(healthCheckUri) .header(HOST, origin.hostAsString()) .build(); } diff --git a/components/client/src/test/unit/java/com/hotels/styx/client/SimpleNettyHttpClientTest.java b/components/client/src/test/unit/java/com/hotels/styx/client/SimpleHttpClientTest.java similarity index 55% rename from components/client/src/test/unit/java/com/hotels/styx/client/SimpleNettyHttpClientTest.java rename to components/client/src/test/unit/java/com/hotels/styx/client/SimpleHttpClientTest.java index 63fdac0800..7c17a611a1 100644 --- a/components/client/src/test/unit/java/com/hotels/styx/client/SimpleNettyHttpClientTest.java +++ b/components/client/src/test/unit/java/com/hotels/styx/client/SimpleHttpClientTest.java @@ -17,31 +17,25 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import com.hotels.styx.api.FullHttpRequest; import com.hotels.styx.api.FullHttpResponse; -import com.hotels.styx.api.HttpClient; import com.hotels.styx.api.HttpRequest; +import com.hotels.styx.api.HttpResponse; import com.hotels.styx.api.client.Connection; -import com.hotels.styx.api.client.ConnectionDestination; -import com.hotels.styx.api.service.ConnectionPoolSettings; import com.hotels.styx.api.service.TlsSettings; -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination; -import com.hotels.styx.client.connectionpool.SimpleConnectionPool; import org.mockito.ArgumentCaptor; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import rx.observers.TestSubscriber; -import rx.subjects.ReplaySubject; +import rx.Observable; import java.io.IOException; import java.util.function.IntConsumer; import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static com.hotels.styx.api.FullHttpRequest.get; import static com.hotels.styx.api.HttpHeaderNames.HOST; import static com.hotels.styx.api.HttpHeaderNames.USER_AGENT; -import static com.hotels.styx.api.HttpRequest.get; -import static com.hotels.styx.api.StyxInternalObservables.fromRxObservable; -import static com.hotels.styx.api.StyxInternalObservables.toRxObservable; import static com.hotels.styx.api.messages.HttpResponseStatus.OK; import static com.hotels.styx.client.Protocol.HTTP; import static com.hotels.styx.client.Protocol.HTTPS; @@ -51,11 +45,13 @@ import static com.hotels.styx.support.server.UrlMatchingStrategies.urlStartingWith; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; -public class SimpleNettyHttpClientTest { - private HttpRequest anyRequest; +public class SimpleHttpClientTest { + private FullHttpRequest anyRequest; private static int MAX_LENGTH = 1024; @BeforeMethod @@ -68,11 +64,7 @@ public void setUp() { @Test public void sendsHttp() throws IOException { withOrigin(HTTP, port -> { - FullHttpResponse response = - await(fromRxObservable(httpClient().sendRequest(httpRequest(port))) - .flatMap(r -> r.toFullResponse(MAX_LENGTH)) - .asCompletableFuture()); - + FullHttpResponse response = await(httpClient().sendRequest(httpRequest(port))); assertThat(response.status(), is(OK)); }); } @@ -80,11 +72,7 @@ public void sendsHttp() throws IOException { @Test public void sendsHttps() throws IOException { withOrigin(HTTPS, port -> { - FullHttpResponse response = httpsClient().sendRequest(httpsRequest(port)) - .flatMap(r -> toRxObservable(r.toFullResponse(MAX_LENGTH))) - .toBlocking() - .single(); - + FullHttpResponse response = await(httpsClient().sendRequest(httpsRequest(port))); assertThat(response.status(), is(OK)); }); } @@ -92,11 +80,7 @@ public void sendsHttps() throws IOException { @Test(expectedExceptions = Exception.class) public void cannotSendHttpsWhenConfiguredForHttp() throws IOException { withOrigin(HTTPS, port -> { - FullHttpResponse response = httpClient().sendRequest(httpsRequest(port)) - .flatMap(r -> toRxObservable(r.toFullResponse(MAX_LENGTH))) - .toBlocking() - .single(); - + FullHttpResponse response = await(httpClient().sendRequest(httpsRequest(port))); assertThat(response.status(), is(OK)); }); } @@ -104,40 +88,33 @@ public void cannotSendHttpsWhenConfiguredForHttp() throws IOException { @Test(expectedExceptions = Exception.class) public void cannotSendHttpWhenConfiguredForHttps() throws IOException { withOrigin(HTTP, port -> { - FullHttpResponse response = httpsClient().sendRequest(httpRequest(port)) - .flatMap(r -> toRxObservable(r.toFullResponse(MAX_LENGTH))) - .toBlocking() - .single(); - + FullHttpResponse response = await(httpsClient().sendRequest(httpRequest(port))); assertThat(response.status(), is(OK)); }); } - private HttpClient httpClient() { - return new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new CloseAfterUseConnectionDestination.Factory()) + private SimpleHttpClient httpClient() { + return new SimpleHttpClient.Builder() .build(); } - private HttpClient httpsClient() { - return new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new CloseAfterUseConnectionDestination.Factory() - .connectionSettings( - new ConnectionSettings(1000)) - .tlsSettings(new TlsSettings.Builder() - .trustAllCerts(true) - .build()) - ) + private SimpleHttpClient httpsClient() { + return new SimpleHttpClient.Builder() + .connectionSettings(new ConnectionSettings(1000)) + .tlsSettings(new TlsSettings.Builder() + .authenticate(false) + .build()) + .responseTimeoutMillis(6000) .build(); } - private HttpRequest httpRequest(int port) { + private FullHttpRequest httpRequest(int port) { return get("http://localhost:" + port) .header(HOST, "localhost:" + port) .build(); } - private HttpRequest httpsRequest(int port) { + private FullHttpRequest httpsRequest(int port) { return get("https://localhost:" + port) .header(HOST, "localhost:" + port) .build(); @@ -159,11 +136,13 @@ private void withOrigin(Protocol protocol, IntConsumer portConsumer) { @Test public void willNotSetAnyUserAgentIfNotSpecified() { Connection mockConnection = mock(Connection.class); - HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(connectInstantlyConnectionDestinationFactory(mockConnection)) + when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(HttpResponse.response().build())); + + SimpleHttpClient client = new SimpleHttpClient.Builder() + .setConnectionFactory((origin, connectionSettings) -> Observable.just(mockConnection)) .build(); - client.sendRequest(anyRequest).subscribe(new TestSubscriber<>()); + client.sendRequest(anyRequest); ArgumentCaptor captor = ArgumentCaptor.forClass(HttpRequest.class); verify(mockConnection).write(captor.capture()); @@ -173,12 +152,14 @@ public void willNotSetAnyUserAgentIfNotSpecified() { @Test public void setsTheSpecifiedUserAgentWhenSpecified() { Connection mockConnection = mock(Connection.class); - HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(connectInstantlyConnectionDestinationFactory(mockConnection)) + when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(HttpResponse.response().build())); + + SimpleHttpClient client = new SimpleHttpClient.Builder() + .setConnectionFactory((origin, connectionSettings) -> Observable.just(mockConnection)) .userAgent("Styx/5.6") .build(); - client.sendRequest(anyRequest).subscribe(new TestSubscriber()); + client.sendRequest(anyRequest); ArgumentCaptor captor = ArgumentCaptor.forClass(HttpRequest.class); verify(mockConnection).write(captor.capture()); @@ -188,16 +169,17 @@ public void setsTheSpecifiedUserAgentWhenSpecified() { @Test public void retainsTheUserAgentStringFromTheRequest() { Connection mockConnection = mock(Connection.class); - HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(connectInstantlyConnectionDestinationFactory(mockConnection)) + when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(HttpResponse.response().build())); + + SimpleHttpClient client = new SimpleHttpClient.Builder() + .setConnectionFactory((origin, connectionSettings) -> Observable.just(mockConnection)) .userAgent("Styx/5.6") .build(); client.sendRequest(get("/foo.txt") .header(USER_AGENT, "Foo/Bar") .header(HOST, "localhost:1234") - .build()) - .subscribe(new TestSubscriber()); + .build()); ArgumentCaptor captor = ArgumentCaptor.forClass(HttpRequest.class); verify(mockConnection).write(captor.capture()); @@ -206,30 +188,10 @@ public void retainsTheUserAgentStringFromTheRequest() { @Test(expectedExceptions = IllegalArgumentException.class) public void requestWithNoHostOrUrlAuthorityCausesException() { - HttpRequest request = get("/foo.txt").build(); - - HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(connectInstantlyConnectionDestinationFactory(mock(Connection.class))) - .build(); + FullHttpRequest request = get("/foo.txt").build(); - client.sendRequest(request) - .flatMap(r -> toRxObservable(r.toFullResponse(MAX_LENGTH))) - .toBlocking() - .single(); - } - - private static Connection.Factory connectInstantlyConnectionFactory(Connection mockConnection) { - return (origin, connectionSettings) -> { - ReplaySubject connectionSubject = ReplaySubject.create(); - connectionSubject.onNext(mockConnection); - connectionSubject.onCompleted(); - return connectionSubject; - }; - } + SimpleHttpClient client = new SimpleHttpClient.Builder().build(); - private static ConnectionDestination.Factory connectInstantlyConnectionDestinationFactory(Connection mockConnection) { - return new SimpleConnectionPool.Factory() - .connectionFactory(connectInstantlyConnectionFactory(mockConnection)) - .connectionPoolSettings(new ConnectionPoolSettings.Builder().build()); + await(client.sendRequest(request)); } } diff --git a/components/client/src/test/unit/java/com/hotels/styx/client/UrlConnectionHttpClientTest.java b/components/client/src/test/unit/java/com/hotels/styx/client/UrlConnectionHttpClientTest.java deleted file mode 100644 index a38e9b5cc4..0000000000 --- a/components/client/src/test/unit/java/com/hotels/styx/client/UrlConnectionHttpClientTest.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright (C) 2013-2018 Expedia Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ -package com.hotels.styx.client; - -import com.github.tomakehurst.wiremock.client.WireMock; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpRequest; -import com.hotels.styx.api.HttpResponse; -import com.hotels.styx.api.client.UrlConnectionHttpClient; -import com.hotels.styx.support.server.FakeHttpServer; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.Test; - -import java.io.IOException; - -import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; -import static com.google.common.net.HttpHeaders.CONTENT_TYPE; -import static com.google.common.net.MediaType.HTML_UTF_8; -import static com.hotels.styx.api.HttpRequest.get; -import static com.hotels.styx.api.HttpRequest.post; -import static com.hotels.styx.api.support.HostAndPorts.freePort; -import static com.hotels.styx.support.api.matchers.HttpResponseBodyMatcher.hasBody; -import static com.hotels.styx.support.api.matchers.HttpResponseStatusMatcher.hasStatus; -import static com.hotels.styx.support.server.UrlMatchingStrategies.urlEndingWith; -import static io.netty.handler.codec.http.HttpMethod.GET; -import static io.netty.handler.codec.http.HttpMethod.POST; -import static com.hotels.styx.api.messages.HttpResponseStatus.METHOD_NOT_ALLOWED; -import static com.hotels.styx.api.messages.HttpResponseStatus.OK; -import static java.lang.String.format; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.allOf; -import static org.hamcrest.Matchers.is; - -public class UrlConnectionHttpClientTest { - int port = freePort(); - FakeHttpServer server = new FakeHttpServer(port); - - String host = format("http://localhost:%d", port); - HttpClient client = new UrlConnectionHttpClient(1000, 3000); - - @BeforeClass - public void startServer() { - this.server.start(); - } - - @AfterClass - public void stopServer() { - this.server.stop(); - } - - @Test - public void handlesGetRequests() throws Exception { - server.stub(urlEndingWith("/get"), aResponse() - .withHeader(CONTENT_TYPE, HTML_UTF_8.toString()) - .withBody(GET.name())); - HttpResponse response = doRequest(request("/get")); - assertThat(response, allOf(hasStatus(OK), hasBody(GET.name()))); - assertThat(response.contentType().get(), is("text/html; charset=utf-8")); - } - - private HttpResponse doRequest(HttpRequest request) { - return this.client.sendRequest(request).toBlocking().first(); - } - - @Test - public void handlesPostRequests() throws IOException { - server.stub(WireMock.post(urlEndingWith("/post")), aResponse().withBody(POST.name())); - HttpRequest request = post(this.host + "/post").build(); - assertThat(doRequest(request), allOf(hasStatus(OK), hasBody(POST.name()))); - } - - @Test - public void handlesErrorResponses() throws IOException { - server.stub(urlEndingWith("/error"), aResponse() - .withStatus(METHOD_NOT_ALLOWED.code()) - .withBody(METHOD_NOT_ALLOWED.toString())); - - assertThat(doRequest(request("/error")), allOf(hasStatus(METHOD_NOT_ALLOWED), hasBody(METHOD_NOT_ALLOWED.toString()))); - } - - private HttpRequest request(String path) { - return get(this.host + path).build(); - } -} diff --git a/components/client/src/test/unit/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheckTest.java b/components/client/src/test/unit/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheckTest.java index b7ab8e0c82..45584d713d 100644 --- a/components/client/src/test/unit/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheckTest.java +++ b/components/client/src/test/unit/java/com/hotels/styx/client/healthcheck/UrlRequestHealthCheckTest.java @@ -15,8 +15,8 @@ */ package com.hotels.styx.client.healthcheck; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpResponse; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpResponse; import com.hotels.styx.api.client.Origin; import com.hotels.styx.api.messages.HttpResponseStatus; import com.hotels.styx.api.metrics.MetricRegistry; @@ -24,11 +24,11 @@ import com.hotels.styx.client.healthcheck.OriginHealthCheckFunction.OriginState; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; -import rx.Observable; import java.io.IOException; +import java.util.concurrent.CompletableFuture; -import static com.hotels.styx.api.HttpResponse.response; +import static com.hotels.styx.api.FullHttpResponse.response; import static com.hotels.styx.api.client.Origin.newOriginBuilder; import static com.hotels.styx.api.messages.HttpResponseStatus.NOT_FOUND; import static com.hotels.styx.api.messages.HttpResponseStatus.OK; @@ -36,7 +36,6 @@ import static com.hotels.styx.client.healthcheck.OriginHealthCheckFunction.OriginState.UNHEALTHY; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import static rx.Observable.just; public class UrlRequestHealthCheckTest { private final Origin someOrigin = newOriginBuilder("localhost", 12345).id("foo").build(); @@ -54,7 +53,7 @@ public void setUp() { @Test public void sendsTheHealthCheckRequestToTheGivenUrl() { - HttpClient client = request -> { + FullHttpClient client = request -> { requestedUrl = request.url().path(); return respondWith(NOT_FOUND); }; @@ -68,7 +67,7 @@ public void sendsTheHealthCheckRequestToTheGivenUrl() { @Test public void declaresOriginHealthyOnOkResponseCode() throws IOException { - HttpClient client = request -> respondWith(OK); + FullHttpClient client = request -> respondWith(OK); new UrlRequestHealthCheck("/version.txt", client, metricRegistry) .check(someOrigin, state -> this.originState = state); @@ -79,7 +78,7 @@ public void declaresOriginHealthyOnOkResponseCode() throws IOException { @Test public void declaresOriginUnhealthyOnNon200Ok() throws IOException { - HttpClient client = request -> respondWith(NOT_FOUND); + FullHttpClient client = request -> respondWith(NOT_FOUND); new UrlRequestHealthCheck("/version.txt", client, metricRegistry) .check(someOrigin, state -> this.originState = state); @@ -91,7 +90,7 @@ public void declaresOriginUnhealthyOnNon200Ok() throws IOException { @Test public void declaredOriginUnhealthyOnTransportException() throws IOException { - HttpClient client = request -> respondWith(new RuntimeException("health check failure, as expected")); + FullHttpClient client = request -> respondWith(new RuntimeException("health check failure, as expected")); new UrlRequestHealthCheck("/version.txt", client, metricRegistry) .check(someOrigin, state -> this.originState = state); @@ -101,11 +100,13 @@ public void declaredOriginUnhealthyOnTransportException() throws IOException { assertThat(metricRegistry.getMeters().size(), is(1)); } - private static Observable respondWith(Throwable error) { - return Observable.error(error); + private static CompletableFuture respondWith(Throwable error) { + CompletableFuture f = new CompletableFuture<>(); + f.completeExceptionally(error); + return f; } - private static Observable respondWith(HttpResponseStatus status) { - return just(response(status).build()); + private static CompletableFuture respondWith(HttpResponseStatus status) { + return CompletableFuture.completedFuture(response(status).build()); } } diff --git a/components/proxy/src/main/java/com/hotels/styx/proxy/BackendServicesRouter.java b/components/proxy/src/main/java/com/hotels/styx/proxy/BackendServicesRouter.java index d78dfb16d4..6af3f3a554 100644 --- a/components/proxy/src/main/java/com/hotels/styx/proxy/BackendServicesRouter.java +++ b/components/proxy/src/main/java/com/hotels/styx/proxy/BackendServicesRouter.java @@ -33,10 +33,9 @@ import com.hotels.styx.client.ConnectionSettings; import com.hotels.styx.client.OriginStatsFactory; import com.hotels.styx.client.OriginsInventory; -import com.hotels.styx.client.SimpleNettyHttpClient; +import com.hotels.styx.client.SimpleHttpClient; import com.hotels.styx.client.StyxHeaderConfig; import com.hotels.styx.client.StyxHostHttpClient; -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination; import com.hotels.styx.client.connectionpool.ConnectionPoolFactory; import com.hotels.styx.client.connectionpool.ExpiringConnectionFactory; import com.hotels.styx.client.healthcheck.OriginHealthCheckFunction; @@ -210,12 +209,8 @@ private static OriginHealthCheckFunction originHealthCheckFunction( ConnectionSettings connectionSettings = new ConnectionSettings( connectionPoolSettings.connectTimeoutMillis()); - HttpClient client = new SimpleNettyHttpClient.Builder() + SimpleHttpClient client = new SimpleHttpClient.Builder() .userAgent("Styx/" + styxVersion) - .connectionDestinationFactory( - new CloseAfterUseConnectionDestination.Factory() - .connectionSettings(connectionSettings) - .connectionFactory(connectionFactory)) .build(); String healthCheckUri = healthCheckConfig diff --git a/components/proxy/src/test/java/com/hotels/styx/StyxServerTest.java b/components/proxy/src/test/java/com/hotels/styx/StyxServerTest.java index e5fdf4d8e3..c3a89e433b 100644 --- a/components/proxy/src/test/java/com/hotels/styx/StyxServerTest.java +++ b/components/proxy/src/test/java/com/hotels/styx/StyxServerTest.java @@ -27,7 +27,6 @@ import com.hotels.styx.api.service.BackendService; import com.hotels.styx.api.service.spi.Registry; import com.hotels.styx.api.service.spi.StyxService; -import com.hotels.styx.api.plugins.spi.PluginFactory; import com.hotels.styx.infrastructure.MemoryBackedRegistry; import com.hotels.styx.infrastructure.RegistryServiceAdapter; import com.hotels.styx.proxy.ProxyServerConfig; diff --git a/components/proxy/src/test/java/com/hotels/styx/proxy/StyxProxyTest.java b/components/proxy/src/test/java/com/hotels/styx/proxy/StyxProxyTest.java index b8efea3c69..98271c1aa8 100644 --- a/components/proxy/src/test/java/com/hotels/styx/proxy/StyxProxyTest.java +++ b/components/proxy/src/test/java/com/hotels/styx/proxy/StyxProxyTest.java @@ -16,13 +16,13 @@ package com.hotels.styx.proxy; import com.google.common.collect.ImmutableList; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpRequest; import com.hotels.styx.api.FullHttpResponse; -import com.hotels.styx.api.HttpClient; import com.hotels.styx.api.HttpInterceptor; import com.hotels.styx.api.HttpResponse; import com.hotels.styx.api.StyxObservable; -import com.hotels.styx.client.SimpleNettyHttpClient; -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination; +import com.hotels.styx.client.SimpleHttpClient; import com.hotels.styx.infrastructure.configuration.yaml.YamlConfig; import com.hotels.styx.routing.handlers.HttpInterceptorPipeline; import com.hotels.styx.server.HttpConnectorConfig; @@ -40,22 +40,15 @@ import static com.hotels.styx.api.io.ResourceFactory.newResource; import static com.hotels.styx.api.messages.HttpResponseStatus.OK; import static com.hotels.styx.api.support.HostAndPorts.freePort; -import static com.hotels.styx.support.api.BlockingObservables.getFirst; -import static java.nio.charset.Charset.defaultCharset; +import static com.hotels.styx.common.StyxFutures.await; import static java.nio.charset.StandardCharsets.UTF_8; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.MatcherAssert.assertThat; -import com.hotels.styx.api.HttpRequest; public class StyxProxyTest extends SSLSetup { - final HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new CloseAfterUseConnectionDestination.Factory()) + final FullHttpClient client = new SimpleHttpClient.Builder() .build(); - private static String content(HttpResponse response) { - return getFirst(response.body()).toString(defaultCharset()); - } - public static void main(String[] args) { NettyServerConfig config = new YamlConfig(newResource("classpath:default.yaml")) .get("proxy", NettyServerConfig.class).get(); @@ -68,7 +61,7 @@ public static void main(String[] args) { } @Test - public void startsAndStopsAServer() throws Exception { + public void startsAndStopsAServer() { HttpServer server = new NettyServerBuilder() .setHttpConnector(connector(freePort())) .build(); @@ -81,7 +74,7 @@ public void startsAndStopsAServer() throws Exception { } @Test - public void startsServerWithHttpConnector() throws Exception { + public void startsServerWithHttpConnector() { HttpInterceptor echoInterceptor = (request, chain) -> textResponse("Response from http connector"); int port = freePort(); @@ -92,8 +85,8 @@ public void startsServerWithHttpConnector() throws Exception { server.startAsync().awaitRunning(); assertThat("Server should be running", server.isRunning()); - HttpResponse secureResponse = get("http://localhost:" + port); - assertThat(content(secureResponse), containsString("Response from http connector")); + FullHttpResponse secureResponse = get("http://localhost:" + port); + assertThat(secureResponse.bodyAs(UTF_8), containsString("Response from http connector")); server.stopAsync().awaitTerminated(); assertThat("Server should not be running", !server.isRunning()); @@ -154,23 +147,23 @@ public void startsServerWithBothHttpAndHttpsConnectors() throws IOException { System.out.println("server is running: " + server.isRunning()); - HttpResponse clearResponse = get("http://localhost:8080/search?q=fanta"); - assertThat(content(clearResponse), containsString("Response from http Connector")); + FullHttpResponse clearResponse = get("http://localhost:8080/search?q=fanta"); + assertThat(clearResponse.bodyAs(UTF_8), containsString("Response from http Connector")); - HttpResponse secureResponse = get("https://localhost:8443/secure"); - assertThat(content(secureResponse), containsString("Response from https Connector")); + FullHttpResponse secureResponse = get("https://localhost:8443/secure"); + assertThat(secureResponse.bodyAs(UTF_8), containsString("Response from https Connector")); server.stopAsync().awaitTerminated(); assertThat("Server should not be running", !server.isRunning()); } - private HttpResponse get(String uri) throws IOException { - HttpRequest secureRequest = HttpRequest.get(uri).build(); + private FullHttpResponse get(String uri) { + FullHttpRequest secureRequest = FullHttpRequest.get(uri).build(); return execute(secureRequest); } - private HttpResponse execute(HttpRequest request) { - return client.sendRequest(request).toBlocking().first(); + private FullHttpResponse execute(FullHttpRequest request) { + return await(client.sendRequest(request)); } } diff --git a/support/test-api/src/test/java/com/hotels/styx/testapi/StyxServerTest.java b/support/test-api/src/test/java/com/hotels/styx/testapi/StyxServerTest.java index 4a1dae7ed7..18df2ac640 100644 --- a/support/test-api/src/test/java/com/hotels/styx/testapi/StyxServerTest.java +++ b/support/test-api/src/test/java/com/hotels/styx/testapi/StyxServerTest.java @@ -18,14 +18,14 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; import com.google.common.collect.ImmutableMap; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpHandler; -import com.hotels.styx.api.client.UrlConnectionHttpClient; +import com.hotels.styx.api.FullHttpClient; import com.hotels.styx.api.FullHttpResponse; -import com.hotels.styx.api.plugins.spi.Plugin; +import com.hotels.styx.api.HttpHandler; +import com.hotels.styx.api.HttpResponse; import com.hotels.styx.api.StyxObservable; -import com.hotels.styx.client.SimpleNettyHttpClient; -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination; +import com.hotels.styx.api.plugins.spi.Plugin; +import com.hotels.styx.api.service.TlsSettings; +import com.hotels.styx.client.SimpleHttpClient; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; @@ -39,11 +39,10 @@ import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static com.hotels.styx.api.HttpRequest.get; -import static com.hotels.styx.api.HttpResponse.response; +import static com.hotels.styx.api.FullHttpRequest.get; import static com.hotels.styx.api.messages.HttpResponseStatus.OK; import static com.hotels.styx.api.support.HostAndPorts.freePort; -import static com.hotels.styx.support.api.BlockingObservables.waitForResponse; +import static com.hotels.styx.common.StyxFutures.await; import static com.hotels.styx.support.matchers.IsOptional.isValue; import static com.hotels.styx.testapi.Origins.origin; import static java.lang.String.format; @@ -59,8 +58,7 @@ import static org.mockito.Mockito.when; public class StyxServerTest { - private final HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new CloseAfterUseConnectionDestination.Factory()) + private final FullHttpClient client = new SimpleHttpClient.Builder() .build(); private StyxServer styxServer; @@ -120,10 +118,9 @@ public void proxiesToOrigin() { .addRoute("/", originServer1.port()) .start(); - FullHttpResponse response = sendGet("/"); + FullHttpResponse response = await(client.sendRequest(get(format("https://localhost:%d/", styxServer.proxyHttpPort())).build())); assertThat(response.status(), is(OK)); - configureFor(originServer1.port()); WireMock.verify(getRequestedFor(urlPathEqualTo("/"))); } @@ -154,10 +151,13 @@ public void proxiesToOriginViaHttps() { .addRoute("/", backendService) .start(); - FullHttpResponse response = sendHttpsGet(styxServer.proxyHttpsPort(), "/"); + SimpleHttpClient tlsClient = new SimpleHttpClient.Builder() + .tlsSettings(new TlsSettings.Builder().build()) + .build(); - assertThat(response.status(), is(OK)); + FullHttpResponse response = await(tlsClient.sendRequest(get(format("https://localhost:%d/", styxServer.proxyHttpsPort())).build())); + assertThat(response.status(), is(OK)); configureFor(secureOriginServer.port()); WireMock.verify(getRequestedFor(urlPathEqualTo("/"))); } @@ -172,10 +172,9 @@ public void proxiesToOriginViaHttpsWithRequestOriginallyHttp() { .addRoute("/", backendService) .start(); - FullHttpResponse response = sendGet("/"); + FullHttpResponse response = await(client.sendRequest(get(format("http://localhost:%d/", styxServer.proxyHttpPort())).build())); assertThat(response.status(), is(OK)); - configureFor(secureOriginServer.port()); WireMock.verify(getRequestedFor(urlPathEqualTo("/"))); } @@ -187,11 +186,12 @@ public void routesCorrectly() { .addRoute("/o2/", originServer2.port()) .start(); - FullHttpResponse response1 = sendGet("/foo"); + FullHttpResponse response1 = await(client.sendRequest(get(format("http://localhost:%d/foo", styxServer.proxyHttpPort())).build())); + assertThat(response1.status(), is(OK)); assertThat(response1.header("origin"), isValue("first")); - FullHttpResponse response2 = sendGet("/o2/foo"); + FullHttpResponse response2 = await(client.sendRequest(get(format("http://localhost:%d/o2/foo", styxServer.proxyHttpPort())).build())); assertThat(response2.status(), is(OK)); assertThat(response2.header("origin"), isValue("second")); @@ -213,7 +213,7 @@ public void executesPluginsWhenProxying() { .addPlugin("response-decorator", responseDecorator) .start(); - FullHttpResponse response = sendGet("/foo"); + FullHttpResponse response = await(client.sendRequest(get(format("http://localhost:%d/foo", styxServer.proxyHttpPort())).build())); assertThat(response.status(), is(OK)); assertThat(response.header("origin"), isValue("first")); assertThat(response.header("plugin-executed"), isValue("yes")); @@ -249,8 +249,8 @@ public void addsPluginLinkToPluginsIndex() { @Test public void addsEndpointLinksToPluginPage() { setUpStyxAndPluginWithAdminPages(ImmutableMap.of( - "adminPage1", (request, ctx)-> StyxObservable.of(response().build()), - "adminPage2", (request, ctx) -> StyxObservable.of(response().build()) + "adminPage1", (request, ctx) -> StyxObservable.of(HttpResponse.response().build()), + "adminPage2", (request, ctx) -> StyxObservable.of(HttpResponse.response().build()) )); FullHttpResponse response = doAdminRequest("/admin/plugins/plugin-with-admin-pages"); @@ -263,8 +263,8 @@ public void addsEndpointLinksToPluginPage() { @Test public void exposesAdminEndpoints() { setUpStyxAndPluginWithAdminPages(ImmutableMap.of( - "adminPage1", (request, ctx) -> StyxObservable.of(response().header("AdminPage1", "yes").build()), - "adminPage2", (request, ctx) -> StyxObservable.of(response().header("AdminPage2", "yes").build()) + "adminPage1", (request, ctx) -> StyxObservable.of(HttpResponse.response().header("AdminPage1", "yes").build()), + "adminPage2", (request, ctx) -> StyxObservable.of(HttpResponse.response().header("AdminPage2", "yes").build()) )); FullHttpResponse response = doAdminRequest("/admin/plugins/plugin-with-admin-pages/adminPage1"); @@ -302,7 +302,7 @@ private Plugin mockPlugin(Map adminInterfaceHandlers) { private FullHttpResponse doAdminRequest(String path) { String url = format("%s://localhost:%s%s", "http", styxServer.adminPort(), startWithSlash(path)); - return waitForResponse(client.sendRequest(get(url).build())); + return await(client.sendRequest(get(url).build())); } @Test @@ -326,11 +326,11 @@ public void canConfigureWithStyxOrigins() { .addRoute("/o2/", origin(originServer2.port())) .start(); - FullHttpResponse response1 = sendGet("/foo"); + FullHttpResponse response1 = await(client.sendRequest(get(format("http://localhost:%d/foo", styxServer.proxyHttpPort())).build())); assertThat(response1.status(), is(OK)); assertThat(response1.header("origin"), isValue("first")); - FullHttpResponse response2 = sendGet("/o2/foo"); + FullHttpResponse response2 = await(client.sendRequest(get(format("http://localhost:%d/o2/foo", styxServer.proxyHttpPort())).build())); assertThat(response2.status(), is(OK)); assertThat(response2.header("origin"), isValue("second")); @@ -347,11 +347,11 @@ public void canConfigureWithBackendService() { .addRoute("/o2/", new BackendService().addOrigin(originServer2.port())) .start(); - FullHttpResponse response1 = sendGet("/foo"); + FullHttpResponse response1 = await(client.sendRequest(get(format("http://localhost:%d/foo", styxServer.proxyHttpPort())).build())); assertThat(response1.status(), is(OK)); assertThat(response1.header("origin"), isValue("first")); - FullHttpResponse response2 = sendGet("/o2/foo"); + FullHttpResponse response2 = await(client.sendRequest(get(format("http://localhost:%d/o2/foo", styxServer.proxyHttpPort())).build())); assertThat(response2.status(), is(OK)); assertThat(response2.header("origin"), isValue("second")); @@ -365,14 +365,9 @@ private FullHttpResponse sendGet(String path) { return doRequest(client, "http", styxServer.proxyHttpPort(), startWithSlash(path)); } - private FullHttpResponse sendHttpsGet(int port, String path) { - UrlConnectionHttpClient client = new UrlConnectionHttpClient(2000, 5000); - return doRequest(client, "https", port, path); - } - - private FullHttpResponse doRequest(HttpClient client, String protocol, int port, String path) { + private FullHttpResponse doRequest(FullHttpClient client, String protocol, int port, String path) { String url = format("%s://localhost:%s%s", protocol, port, startWithSlash(path)); - return waitForResponse(client.sendRequest(get(url).build())); + return await(client.sendRequest(get(url).build())); } private String startWithSlash(String path) { diff --git a/system-tests/e2e-suite/src/test/java/com/hotels/styx/http/StaticFileOnRealServerIT.java b/system-tests/e2e-suite/src/test/java/com/hotels/styx/http/StaticFileOnRealServerIT.java index 47ca6acd71..c57cd428c3 100644 --- a/system-tests/e2e-suite/src/test/java/com/hotels/styx/http/StaticFileOnRealServerIT.java +++ b/system-tests/e2e-suite/src/test/java/com/hotels/styx/http/StaticFileOnRealServerIT.java @@ -16,15 +16,15 @@ package com.hotels.styx.http; import com.google.common.io.Files; -import com.hotels.styx.api.HttpRequest; -import com.hotels.styx.api.HttpResponse; -import com.hotels.styx.client.SimpleNettyHttpClient; -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination; +import com.hotels.styx.api.FullHttpRequest; +import com.hotels.styx.api.FullHttpResponse; +import com.hotels.styx.client.SimpleHttpClient; import com.hotels.styx.server.HttpServer; import com.hotels.styx.server.handlers.StaticFileHandler; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import com.hotels.styx.api.FullHttpClient; import java.io.File; import java.io.FileWriter; @@ -33,14 +33,14 @@ import static com.hotels.styx.api.messages.HttpMethod.GET; import static com.hotels.styx.api.support.HostAndPorts.freePort; +import static com.hotels.styx.common.StyxFutures.await; import static com.hotels.styx.server.HttpServers.createHttpServer; -import static com.hotels.styx.support.api.matchers.HttpResponseBodyMatcher.hasBody; +import static java.nio.charset.StandardCharsets.UTF_8; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; public class StaticFileOnRealServerIT { - private final com.hotels.styx.api.HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new CloseAfterUseConnectionDestination.Factory()) - .build(); + private final FullHttpClient client = new SimpleHttpClient.Builder().build(); private HttpServer webServer; private File dir; @@ -72,15 +72,12 @@ public void shouldWorkInRealServer() throws Exception { mkdir("some/dir"); writeFile("some/dir/content1.txt", "some txt"); - HttpRequest request = new HttpRequest.Builder(GET, "/index.html") + FullHttpRequest request = new FullHttpRequest.Builder(GET, "/index.html") .header("Host", serverEndpoint) .build(); - HttpResponse response = execute(request); - assertThat(response, hasBody("Hello World")); - } - private HttpResponse execute(HttpRequest request) { - return client.sendRequest(request).toBlocking().first(); + FullHttpResponse response = await(client.sendRequest(request)); + assertThat(response.bodyAs(UTF_8), is("Hello World")); } private void mkdir(String path) { diff --git a/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/ProtocolMetricsTest.java b/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/ProtocolMetricsTest.java index 2f96b582bc..d055b6487a 100644 --- a/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/ProtocolMetricsTest.java +++ b/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/ProtocolMetricsTest.java @@ -17,13 +17,11 @@ import com.github.tomakehurst.wiremock.WireMockServer; import com.github.tomakehurst.wiremock.client.WireMock; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpRequest; import com.hotels.styx.api.FullHttpResponse; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpRequest; import com.hotels.styx.api.StyxObservable; -import com.hotels.styx.api.client.UrlConnectionHttpClient; -import com.hotels.styx.client.SimpleNettyHttpClient; -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination; +import com.hotels.styx.client.SimpleHttpClient; import com.hotels.styx.testapi.StyxServer; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -38,9 +36,9 @@ import static com.github.tomakehurst.wiremock.client.WireMock.stubFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlPathEqualTo; import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static com.hotels.styx.api.HttpRequest.get; +import static com.hotels.styx.api.FullHttpRequest.get; import static com.hotels.styx.api.support.HostAndPorts.freePort; -import static com.hotels.styx.support.api.BlockingObservables.waitForResponse; +import static com.hotels.styx.common.StyxFutures.await; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; @@ -49,9 +47,7 @@ import static org.hamcrest.Matchers.is; public class ProtocolMetricsTest { - private final HttpClient client = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new CloseAfterUseConnectionDestination.Factory()) - .build(); + private final FullHttpClient client = new SimpleHttpClient.Builder().build(); private StyxServer styxServer; @@ -132,18 +128,18 @@ private FullHttpResponse doGet(String path) { } private FullHttpResponse doHttpsGet(String path) { - UrlConnectionHttpClient client1 = new UrlConnectionHttpClient(2000, 5000); + FullHttpClient client1 = new SimpleHttpClient.Builder().build(); return doRequest(client1, "https", styxServer.proxyHttpsPort(), path); } - private static FullHttpResponse doRequest(HttpClient client, String protocol, int port, String path) { + private static FullHttpResponse doRequest(FullHttpClient client, String protocol, int port, String path) { String url = format("%s://localhost:%s%s", protocol, port, startWithSlash(path)); - HttpRequest request = get(url) - .body(body("foo", "bar", "baz")) + FullHttpRequest request = get(url) + .body("foobarbaz", UTF_8) .build(); - return waitForResponse(client.sendRequest(request)); + return await(client.sendRequest(request)); } // used to ensure that we do not increment counters for successive chunks diff --git a/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/StyxMetrics.java b/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/StyxMetrics.java index 679a111f89..111e019118 100644 --- a/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/StyxMetrics.java +++ b/system-tests/e2e-suite/src/test/java/com/hotels/styx/metrics/StyxMetrics.java @@ -19,10 +19,9 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Joiner; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpRequest; -import com.hotels.styx.api.HttpResponse; -import com.hotels.styx.api.client.UrlConnectionHttpClient; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpResponse; +import com.hotels.styx.client.SimpleHttpClient; import com.hotels.styx.support.Meter; import com.hotels.styx.utils.MetricsSnapshot; @@ -38,9 +37,10 @@ import java.util.regex.Pattern; import static com.google.common.base.Preconditions.checkArgument; -import static com.hotels.styx.api.HttpRequest.get; -import static com.hotels.styx.support.api.HttpMessageBodies.bodyAsString; +import static com.hotels.styx.api.FullHttpRequest.get; +import static com.hotels.styx.common.StyxFutures.await; import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.emptyMap; import static java.util.Comparator.comparing; import static java.util.Objects.requireNonNull; @@ -159,10 +159,9 @@ private static Object toGauge(Map map) { } private static String downloadJsonString(String host, int port) { - HttpClient client = new UrlConnectionHttpClient(1000, 3000); - HttpRequest request = get(format("http://%s:%d/admin/metrics", host, port)).build(); - HttpResponse response = client.sendRequest(request).toBlocking().first(); - return bodyAsString(response); + FullHttpClient client = new SimpleHttpClient.Builder().build(); + FullHttpResponse response = await(client.sendRequest(get(format("http://%s:%d/admin/metrics", host, port)).build())); + return response.bodyAs(UTF_8); } private static Map decodeToMap(String body) throws IOException { diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/StyxClientSupplier.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/StyxClientSupplier.scala index ac2219b131..c673e75246 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/StyxClientSupplier.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/StyxClientSupplier.scala @@ -15,65 +15,52 @@ */ package com.hotels.styx -import com.hotels.styx.api.StyxInternalObservables.toRxObservable -import com.hotels.styx.api.client.UrlConnectionHttpClient -import com.hotels.styx.api.{FullHttpResponse, HttpClient, HttpRequest, HttpResponse} -import com.hotels.styx.client.HttpConfig.newHttpConfigBuilder -import com.hotels.styx.client.HttpRequestOperationFactory.Builder.httpRequestOperationFactoryBuilder -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination.Factory -import com.hotels.styx.client.netty.connectionpool.NettyConnectionFactory -import com.hotels.styx.client.{ConnectionSettings, SimpleNettyHttpClient} -import rx.lang.scala.JavaConversions.toScalaObservable -import rx.lang.scala.Observable - +import com.hotels.styx.api._ +import com.hotels.styx.api.service.TlsSettings +import com.hotels.styx.client.{ConnectionSettings, SimpleHttpClient} +import scala.concurrent.{Await, Future} import scala.concurrent.duration._ +import scala.compat.java8.FutureConverters.CompletionStageOps +import scala.concurrent.ExecutionContext.Implicits.global trait StyxClientSupplier { val TWO_SECONDS: Int = 2 * 1000 val FIVE_SECONDS: Int = 5 * 1000 - val client: HttpClient = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new Factory() - .connectionSettings(new ConnectionSettings(1000)) - .connectionFactory(new NettyConnectionFactory.Builder() - .name("scalatest-e2e-client") - .httpConfig(newHttpConfigBuilder().setMaxHeadersSize(2 * 8192).build()) - .httpRequestOperationFactory(httpRequestOperationFactoryBuilder().build()) - .build()) - ) - .build + val client: FullHttpClient = new SimpleHttpClient.Builder() + .threadName("scalatest-e2e-client") + .connectionSettings(new ConnectionSettings(1000)) + .maxHeaderSize(2 * 8192) + .build() + + val httpsClient: FullHttpClient = new SimpleHttpClient.Builder() + .threadName("scalatest-e2e-secure-client") + .connectionSettings(new ConnectionSettings(1000)) + .maxHeaderSize(2 * 8192) + .tlsSettings(new TlsSettings.Builder().build()) + .build() - val httpsClient: HttpClient = new UrlConnectionHttpClient(TWO_SECONDS, FIVE_SECONDS) - private def doHttpRequest(request: HttpRequest, debug: Boolean = false): Observable[HttpResponse] = toScalaObservable(client.sendRequest(request)) + private def doHttpRequest(request: FullHttpRequest, debug: Boolean = false): Future[FullHttpResponse] = client.sendRequest(request).toScala - private def doSecureRequest(request: HttpRequest): Observable[HttpResponse] = httpsClient.sendRequest(request) + private def doSecureRequest(request: FullHttpRequest): Future[FullHttpResponse] = httpsClient.sendRequest(request).toScala - private def doRequest(request: HttpRequest, debug: Boolean = false): Observable[HttpResponse] = if (request.isSecure) + private def doRequest(request: FullHttpRequest, debug: Boolean = false): Future[FullHttpResponse] = if (request.isSecure) doSecureRequest(request) else doHttpRequest(request, debug = debug) - def decodedRequest(request: HttpRequest, + def decodedRequest(request: FullHttpRequest, debug: Boolean = false, maxSize: Int = 1024 * 1024, timeout: Duration = 30.seconds): FullHttpResponse = { - doRequest(request, debug = debug) - .doOnNext(response => if (debug) println("StyxClientSupplier: received response for: " + request.url().path())) - .flatMap(response => toRxObservable(response.toFullResponse(maxSize))) - .timeout(timeout) - .toBlocking - .first + val future = doRequest(request, debug = debug) + .map(response => { + if (debug) { + println("StyxClientSupplier: received response for: " + request.url().path()) + } + response + }) + Await.result(future, timeout) } - def decodedRequestWithClient(client: HttpClient, - request: HttpRequest, - debug: Boolean = false, - maxSize: Int = 1024 * 1024, timeout: Duration = 30.seconds): FullHttpResponse = { - toScalaObservable(client.sendRequest(request)) - .doOnNext(response => if (debug) println("StyxClientSupplier: received response for: " + request.url().path())) - .flatMap(response => toRxObservable(response.toFullResponse(maxSize))) - .timeout(timeout) - .toBlocking - .first - } } diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/AdminSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/AdminSpec.scala index 040ce74363..9f795c0366 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/AdminSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/AdminSpec.scala @@ -17,7 +17,7 @@ package com.hotels.styx.admin import java.nio.charset.StandardCharsets.UTF_8 -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.infrastructure.HttpResponseImplicits import com.hotels.styx.{DefaultStyxConfiguration, StyxClientSupplier, StyxProxySpec} diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/FileBasedOriginsFileChangeMonitorSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/FileBasedOriginsFileChangeMonitorSpec.scala index 747369ca41..bfd64144f8 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/FileBasedOriginsFileChangeMonitorSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/FileBasedOriginsFileChangeMonitorSpec.scala @@ -39,7 +39,6 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING import com.google.common.io.Files.createTempDir import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus -import com.hotels.styx.support.api.BlockingObservables.waitForResponse import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration._ import com.hotels.styx.{StyxClientSupplier, StyxServerSupport} @@ -110,15 +109,15 @@ class FileBasedOriginsFileChangeMonitorSpec extends FunSpec } it("Automatically detects changes in origins file.") { - waitForResponse(client.sendRequest(reqToApp01.toStreamingRequest)).status() should be (HttpResponseStatus.OK) - waitForResponse(client.sendRequest(reqToApp02.toStreamingRequest)).status() should be (HttpResponseStatus.BAD_GATEWAY) + decodedRequest(reqToApp01).status() should be (HttpResponseStatus.OK) + decodedRequest(reqToApp02).status() should be (HttpResponseStatus.BAD_GATEWAY) writeConfig(styxOriginsFile, configTemplate.format("appv2", "/app02/", origin.port())) Thread.sleep(2000) - waitForResponse(client.sendRequest(reqToApp01.toStreamingRequest)).status() should be (HttpResponseStatus.BAD_GATEWAY) - waitForResponse(client.sendRequest(reqToApp02.toStreamingRequest)).status() should be (HttpResponseStatus.OK) + decodedRequest(reqToApp01).status() should be (HttpResponseStatus.BAD_GATEWAY) + decodedRequest(reqToApp02).status() should be (HttpResponseStatus.OK) } def writeConfig(path: Path, text: String): Unit = { diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/HealthCheckSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/HealthCheckSpec.scala index 3182b80969..6c237c18c4 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/HealthCheckSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/HealthCheckSpec.scala @@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.hotels.styx.api.HttpHeaderNames.HOST import com.hotels.styx.api.HttpInterceptor.{Chain} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api._ import com.hotels.styx.api.messages.HttpResponseStatus.INTERNAL_SERVER_ERROR import com.hotels.styx.infrastructure.HttpResponseImplicits diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsCommandsSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsCommandsSpec.scala index ddbb0d9007..22992f4c8e 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsCommandsSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsCommandsSpec.scala @@ -170,11 +170,11 @@ class OriginsCommandsSpec extends FeatureSpec def getStyxMetricsSnapshot: String = get(styxServer.adminURL("/admin/metrics")).bodyAs(UTF_8) private def get(url: String): FullHttpResponse = { - decodedRequest(HttpRequest.get(url).build()) + decodedRequest(FullHttpRequest.get(url).build()) } private def post(url: String, content: String) = { - decodedRequest(HttpRequest.post(url).body(content).build()) + decodedRequest(FullHttpRequest.post(url).body(content, UTF_8).build()) } def configureAndStart(appId: String, originId: String): FakeHttpServer = { diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsPathDuplicationOnReloadSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsPathDuplicationOnReloadSpec.scala index a80492a596..4cd7a61d33 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsPathDuplicationOnReloadSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsPathDuplicationOnReloadSpec.scala @@ -19,7 +19,7 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING import java.nio.file.{Files, Paths} import com.google.common.io.Files.createTempDir -import com.hotels.styx.api.HttpRequest.post +import com.hotels.styx.api.FullHttpRequest.post import com.hotels.styx.api.messages.HttpResponseStatus.INTERNAL_SERVER_ERROR import com.hotels.styx.proxy.backends.file.FileBackedBackendServicesRegistry import com.hotels.styx.support.ResourcePaths.fixturesHome diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsReloadCommandSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsReloadCommandSpec.scala index 48626f9e45..722379c067 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsReloadCommandSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/admin/OriginsReloadCommandSpec.scala @@ -19,7 +19,7 @@ import java.nio.file.StandardCopyOption.REPLACE_EXISTING import java.nio.file.{Files, Paths} import com.google.common.io.Files.createTempDir -import com.hotels.styx.api.HttpRequest.post +import com.hotels.styx.api.FullHttpRequest.post import com.hotels.styx.api.messages.HttpResponseStatus.INTERNAL_SERVER_ERROR import com.hotels.styx.proxy.backends.file.FileBackedBackendServicesRegistry import com.hotels.styx.support.ResourcePaths.fixturesHome diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/CipherSuitesSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/CipherSuitesSpec.scala index 22ce36b5d5..6166682b05 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/CipherSuitesSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/CipherSuitesSpec.scala @@ -20,7 +20,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ import com.github.tomakehurst.wiremock.client.{ValueMatchingStrategy, WireMock} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/OriginClosesConnectionSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/OriginClosesConnectionSpec.scala index 7bf7d850c0..3b3837bb08 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/OriginClosesConnectionSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/OriginClosesConnectionSpec.scala @@ -17,13 +17,12 @@ package com.hotels.styx.client import ch.qos.logback.classic.Level import com.google.common.base.Charsets._ -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.{HttpResponse, service} import com.hotels.styx.api.client.ActiveOrigins import com.hotels.styx.api.client.loadbalancing.spi.LoadBalancer import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.api.netty.exceptions.ResponseTimeoutException -import com.hotels.styx.api.service.spi import com.hotels.styx.client.OriginsInventory.newOriginsInventoryBuilder import com.hotels.styx.client.loadbalancing.strategies.BusyConnectionsStrategy import com.hotels.styx.client.stickysession.StickySessionLoadBalancingStrategy @@ -124,7 +123,8 @@ class OriginClosesConnectionSpec extends FunSuite val responseObservable = styxClient.sendRequest( get("/foo/3") .addHeader(HOST, originHost) - .build()) + .build() + .toStreamingRequest) responseObservable .doOnNext((t: HttpResponse) => toRxObservable(t.body()).subscribe(contentSubscriber)) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/TlsVersionSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/TlsVersionSpec.scala index 17fba8627b..144f09df8d 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/TlsVersionSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/client/TlsVersionSpec.scala @@ -17,7 +17,7 @@ package com.hotels.styx.client import com.github.tomakehurst.wiremock.client.WireMock._ import com.github.tomakehurst.wiremock.client.{ValueMatchingStrategy, WireMock} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginContentOverflowSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginContentOverflowSpec.scala index cbe5a8cf87..69ed9985a0 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginContentOverflowSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginContentOverflowSpec.scala @@ -18,7 +18,7 @@ package com.hotels.styx.plugins import java.nio.charset.StandardCharsets.UTF_8 import com.hotels.styx.MockServer.responseSupplier -import com.hotels.styx.api.HttpRequest._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.{HttpResponse, StyxInternalObservables} import com.hotels.styx.api.HttpResponse._ import com.hotels.styx.api.messages.HttpResponseStatus.BAD_GATEWAY diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginSpec.scala index 8c855aff74..6d1646b540 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AggregatingPluginSpec.scala @@ -18,18 +18,16 @@ package com.hotels.styx.plugins import java.nio.charset.StandardCharsets.UTF_8 import com.hotels.styx.MockServer.responseSupplier -import com.hotels.styx.api.HttpRequest._ -import com.hotels.styx.api.{HttpResponse, StyxObservable} -import com.hotels.styx.api.HttpResponse._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.HttpResponse.response +import com.hotels.styx.api.StyxObservable import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} import com.hotels.styx.{MockServer, StyxProxySpec} import io.netty.buffer.{ByteBuf, Unpooled} -import com.hotels.styx.api.messages.HttpResponseStatus import org.scalatest.FunSpec import org.scalatest.concurrent.Eventually -import rx.Observable.just + import scala.collection.JavaConverters._ import scala.concurrent.duration._ diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestContentSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestContentSpec.scala index 2c7fd9ecbb..5c7f239852 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestContentSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestContentSpec.scala @@ -20,10 +20,9 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx._ import com.hotels.styx.api.HttpInterceptor.Chain -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.StyxInternalObservables.{fromRxObservable, toRxObservable} -import com.hotels.styx.api.{HttpRequest, HttpResponse, StyxInternalObservables, StyxObservable} -import com.hotels.styx.support.api.BlockingObservables.waitForResponse +import com.hotels.styx.api.{HttpRequest, HttpResponse, StyxObservable} import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} import com.hotels.styx.support.server.UrlMatchingStrategies._ @@ -33,6 +32,9 @@ import io.netty.handler.codec.http.HttpHeaders.Values._ import org.scalatest.{BeforeAndAfterAll, FunSpec} import scala.concurrent.duration._ +import scala.compat.java8.FutureConverters.CompletionStageOps +import scala.concurrent.Await + class AsyncRequestContentSpec extends FunSpec with StyxProxySpec @@ -68,7 +70,7 @@ class AsyncRequestContentSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = waitForResponse(client.sendRequest(request)) + val response = Await.result(client.sendRequest(request).toScala, 10.seconds) mockServer.verify(1, getRequestedFor(urlStartingWith("/foobar"))) response.bodyAs(UTF_8) should be("I should be here!") diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestSpec.scala index b4ca55801a..31ab7c6923 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncRequestSpec.scala @@ -16,27 +16,23 @@ package com.hotels.styx.plugins import java.nio.charset.StandardCharsets.UTF_8 -import java.util.concurrent.CompletableFuture import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx._ import com.hotels.styx.api.HttpInterceptor.Chain -import com.hotels.styx.api.HttpRequest.get -import com.hotels.styx.api.StyxCoreObservable -import com.hotels.styx.api.{HttpInterceptor, HttpRequest, HttpResponse, StyxObservable} -import com.hotels.styx.common.CompletableFutures -import com.hotels.styx.support.api.BlockingObservables.waitForResponse +import com.hotels.styx.api.FullHttpRequest.get +import com.hotels.styx.api.{HttpRequest, HttpResponse, StyxObservable} import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} import com.hotels.styx.support.server.UrlMatchingStrategies._ import io.netty.handler.codec.http.HttpHeaders.Names._ import io.netty.handler.codec.http.HttpHeaders.Values._ import org.scalatest.FunSpec -import rx.lang.scala.Observable import scala.compat.java8.functionConverterImpls.AsJavaFunction -import scala.concurrent.Future +import scala.concurrent.{Await, Future} import scala.concurrent.duration._ +import scala.compat.java8.FutureConverters.CompletionStageOps class AsyncRequestSpec extends FunSpec with StyxProxySpec @@ -69,7 +65,7 @@ class AsyncRequestSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = waitForResponse(client.sendRequest(request)) + val response = Await.result(client.sendRequest(request).toScala, 5.seconds) mockServer.verify(1, getRequestedFor(urlStartingWith("/foobar"))) response.bodyAs(UTF_8) should be("I should be here!") diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseContentSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseContentSpec.scala index 49141df880..1897cae584 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseContentSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseContentSpec.scala @@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx.api.HttpInterceptor.Chain -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api._ import com.hotels.styx.support._ import com.hotels.styx.support.api.BlockingObservables.waitForResponse @@ -72,7 +72,7 @@ class AsyncResponseContentSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = waitForResponse(client.sendRequest(request)) + val response = decodedRequest(request) mockServer.verify(1, getRequestedFor(urlStartingWith("/foobar"))) response.bodyAs(UTF_8) should be("I should be here!") diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseSpec.scala index ec8492b677..3173719bd2 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/AsyncResponseSpec.scala @@ -20,7 +20,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx._ import com.hotels.styx.api.HttpInterceptor.Chain -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.{HttpInterceptor, HttpRequest, HttpResponse, StyxObservable} import com.hotels.styx.support.api.BlockingObservables.waitForResponse import com.hotels.styx.support.backends.FakeHttpServer @@ -70,7 +70,7 @@ class AsyncPluginResponseSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = waitForResponse(client.sendRequest(request)) + val response = decodedRequest(request) mockServer.verify(1, getRequestedFor(urlStartingWith("/foobar"))) response.bodyAs(UTF_8) should be("I should be here!") diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ErrorMetricsSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ErrorMetricsSpec.scala index e083f73af4..6e929b61ec 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ErrorMetricsSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ErrorMetricsSpec.scala @@ -37,7 +37,7 @@ import com.hotels.styx._ import com.hotels.styx.{BackendServicesRegistrySupplier, StyxClientSupplier, StyxConfiguration, StyxServerSupport} import com.hotels.styx.api.HttpHeaderNames.HOST import com.hotels.styx.api.HttpInterceptor.{Chain} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.HttpResponse.response import com.hotels.styx.api.messages.HttpResponseStatus import com.hotels.styx.api._ diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginAdminInterfaceSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginAdminInterfaceSpec.scala index 92ba0d9669..6aae8c482f 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginAdminInterfaceSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginAdminInterfaceSpec.scala @@ -100,7 +100,7 @@ class PluginAdminInterfaceSpec extends FunSpec with StyxProxySpec with StyxClien } private def get(url: String) = { - decodedRequest(HttpRequest.get(url).build()) + decodedRequest(FullHttpRequest.get(url).build()) } def styxHostAndPort: HostAndPort = { diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginErrorHandlingSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginErrorHandlingSpec.scala index aa8db37071..0a03097acc 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginErrorHandlingSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginErrorHandlingSpec.scala @@ -15,10 +15,11 @@ */ package com.hotels.styx.plugins +import java.nio.charset.StandardCharsets.UTF_8 import java.util.Optional import com.hotels.styx._ -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api._ import com.hotels.styx.api.messages.HttpResponseStatus.INTERNAL_SERVER_ERROR import com.hotels.styx.support.configuration.{ConnectionPoolSettings, HttpBackend, Origins, StyxConfig} @@ -72,7 +73,7 @@ class PluginErrorHandlingSpec extends FunSpec for (i <- 1 to 2) { val request = get(styxServer.routerURL("/foo")) .header("Fail_after_handle", "true") - .body("foo") + .body("foo", UTF_8) .build() val resp = decodedRequest(request) assert(resp.status() == INTERNAL_SERVER_ERROR) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginPipelineSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginPipelineSpec.scala index c902c5653f..a066b9692f 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginPipelineSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginPipelineSpec.scala @@ -17,10 +17,10 @@ package com.hotels.styx.plugins import com.google.common.net.HostAndPort import com.google.common.net.HostAndPort._ -import com.hotels.styx.{ExamplePluginJarLocation, StyxProxySpec} -import com.hotels.styx.api.HttpRequest -import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} +import com.hotels.styx.api.FullHttpRequest import com.hotels.styx.support.backends.FakeHttpServer +import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} +import com.hotels.styx.{ExamplePluginJarLocation, StyxProxySpec} import org.scalatest.FunSpec class PluginPipelineSpec extends FunSpec with StyxProxySpec { @@ -70,8 +70,8 @@ class PluginPipelineSpec extends FunSpec with StyxProxySpec { fromParts("localhost", styxServer.httpPort) } - def anHttpRequest: HttpRequest = { - HttpRequest.get(styxServer.routerURL("/pluginPipelineSpec/")).build() + def anHttpRequest: FullHttpRequest = { + FullHttpRequest.get(styxServer.routerURL("/pluginPipelineSpec/")).build() } } diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginToggleSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginToggleSpec.scala index 24db6585db..5e774032ee 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginToggleSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/PluginToggleSpec.scala @@ -13,21 +13,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -/** - * Copyright (C) 2013-2018 Expedia Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package com.hotels.styx.plugins import java.nio.charset.StandardCharsets.UTF_8 @@ -53,11 +38,11 @@ class PluginToggleSpec extends FunSpec with StyxProxySpec with StyxClientSupplie override protected def beforeEach(): Unit = { setPluginEnabled("true") - val resp1 = decodedRequest(get(styxServer.adminURL("/admin/plugins")).build().toStreamingRequest) + val resp1 = decodedRequest(get(styxServer.adminURL("/admin/plugins")).build()) resp1.status() should be(OK) resp1.bodyAs(UTF_8) should include("

Enabled

pluginUnderTest

Disabled

") - val resp2 = decodedRequest(get(styxServer.routerURL("/")).build().toStreamingRequest) + val resp2 = decodedRequest(get(styxServer.routerURL("/")).build()) resp2.status() should be(OK) resp2.bodyAs(UTF_8) should include("response-from-plugin") @@ -73,7 +58,7 @@ class PluginToggleSpec extends FunSpec with StyxProxySpec with StyxClientSupplie it("Should move the plugin to disabled when toggled") { disablePlugin() - val resp = decodedRequest(get(styxServer.adminURL("/admin/plugins")).build().toStreamingRequest) + val resp = decodedRequest(get(styxServer.adminURL("/admin/plugins")).build()) resp.status() should be(OK) resp.bodyAs(UTF_8) should include("

Enabled

Disabled

pluginUnderTest
") @@ -82,7 +67,7 @@ class PluginToggleSpec extends FunSpec with StyxProxySpec with StyxClientSupplie it("Plugin should not be called when disabled") { disablePlugin() - val resp = decodedRequest(get(styxServer.routerURL("/")).build().toStreamingRequest) + val resp = decodedRequest(get(styxServer.routerURL("/")).build()) resp.status() should be(OK) } @@ -108,8 +93,7 @@ class PluginToggleSpec extends FunSpec with StyxProxySpec with StyxClientSupplie val resp = decodedRequest( put(styxServer.adminURL("/admin/tasks/plugin/pluginUnderTest/enabled")) .body(enabled, UTF_8) - .build() - .toStreamingRequest) + .build()) resp.status() should be(OK) resp.bodyAs(UTF_8) @@ -118,8 +102,7 @@ class PluginToggleSpec extends FunSpec with StyxProxySpec with StyxClientSupplie private def checkPluginEnabled(): String = { val resp = decodedRequest( get(styxServer.adminURL("/admin/tasks/plugin/pluginUnderTest/enabled")) - .build() - .toStreamingRequest) + .build()) resp.status() should be(OK) resp.bodyAs(UTF_8) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ResubscribingPluginSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ResubscribingPluginSpec.scala index bef5b45d6e..fe1e7b4eca 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ResubscribingPluginSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/plugins/ResubscribingPluginSpec.scala @@ -19,7 +19,7 @@ import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx._ import com.hotels.styx.api.HttpHeaderNames.TRANSFER_ENCODING import com.hotels.styx.api.HttpHeaderValues.CHUNKED -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.INTERNAL_SERVER_ERROR import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.server.UrlMatchingStrategies._ @@ -27,6 +27,8 @@ import org.hamcrest.MatcherAssert.assertThat import org.hamcrest.Matchers.is import org.scalatest.FunSpec +// TODO: Mikko no longer necessary? + class ResubscribingPluginSpec extends FunSpec with StyxProxySpec with DefaultStyxConfiguration { @@ -64,7 +66,7 @@ class ResubscribingPluginSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = client.sendRequest(request).toBlocking.single() + val response = decodedRequest(request) assertThat(response.status(), is(INTERNAL_SERVER_ERROR)) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadFramingSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadFramingSpec.scala index 567ec1bc55..29b0390f45 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadFramingSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadFramingSpec.scala @@ -21,6 +21,7 @@ import com.github.tomakehurst.wiremock.client.WireMock._ import com.google.common.base.Charsets.UTF_8 import com.google.common.net.HostAndPort._ import com.hotels.styx._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.{BAD_REQUEST, OK} import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins} @@ -84,7 +85,7 @@ class BadFramingSpec extends FunSpec it("Returns BAD_REQUEST Bad Request if client request contains multiple differing content-length headers.") { originRespondingWith(status200OkResponse) - val request = api.HttpRequest.get(styxServer.routerURL("/badFramingSpec/one/foo/e")) + val request = get(styxServer.routerURL("/badFramingSpec/one/foo/e")) .disableValidation() .addHeader(CONTENT_LENGTH, "50") .addHeader(CONTENT_LENGTH, "60") @@ -97,7 +98,7 @@ class BadFramingSpec extends FunSpec it("Returns BAD_REQUEST Bad Request if client request contains multiple differing content-length values.") { originRespondingWith(status200OkResponse) - val request = api.HttpRequest.get(styxServer.routerURL("/badFramingSpec/one/foo/f")) + val request = get(styxServer.routerURL("/badFramingSpec/one/foo/f")) .disableValidation() .header(CONTENT_LENGTH, "50, 60") .build() @@ -109,7 +110,7 @@ class BadFramingSpec extends FunSpec it("Returns BAD_REQUEST Bad Request if client request contains multiple identical content-length values.") { originRespondingWith(status200OkResponse) - val request = api.HttpRequest.get(styxServer.routerURL("/badFramingSpec/one/foo/g")) + val request = get(styxServer.routerURL("/badFramingSpec/one/foo/g")) .disableValidation() .header(CONTENT_LENGTH, "50, 50") .build() @@ -131,7 +132,7 @@ class BadFramingSpec extends FunSpec ctx.writeAndFlush(new DefaultLastHttpContent(copiedBuffer("c" * 30, UTF_8))) } }) - val request = api.HttpRequest.get(styxServer.routerURL("/badFramingSpec/one/foo/i")) + val request = get(styxServer.routerURL("/badFramingSpec/one/foo/i")) .build() val response = decodedRequest(request) response.status() should be(OK) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadResponseFromOriginSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadResponseFromOriginSpec.scala index 7f0723d8c1..5b25993018 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadResponseFromOriginSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BadResponseFromOriginSpec.scala @@ -16,13 +16,14 @@ package com.hotels.styx.proxy import com.google.common.base.Charsets.UTF_8 +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.BAD_GATEWAY import com.hotels.styx.client.StyxHeaderConfig.STYX_INFO_DEFAULT import com.hotels.styx.support.configuration.{ConnectionPoolSettings, HttpBackend, Origins} import com.hotels.styx.support.matchers.IsOptional.matches import com.hotels.styx.support.matchers.RegExMatcher.matchesRegex import com.hotels.styx.support.{NettyOrigins, TestClientSupport} -import com.hotels.styx.{DefaultStyxConfiguration, StyxProxySpec, api} +import com.hotels.styx.{DefaultStyxConfiguration, StyxProxySpec} import io.netty.buffer.Unpooled import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.http.HttpHeaders.Names.{CONTENT_LENGTH, HOST, TRANSFER_ENCODING} @@ -102,7 +103,7 @@ class BadResponseFromOriginSpec extends FunSpec )) - val request = api.HttpRequest.get(styxServer.routerURL("/badResponseFromOriginSpec/3")).build() + val request = get(styxServer.routerURL("/badResponseFromOriginSpec/3")).build() val response = decodedRequest(request) response.status() should be(BAD_GATEWAY) assertThat(response.headers().get(STYX_INFO_DEFAULT), matches(matchesRegex("noJvmRouteSet;[0-9a-f-]+"))) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BigFileDownloadSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BigFileDownloadSpec.scala index cc0a9d9055..ef42f8fdfd 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BigFileDownloadSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/BigFileDownloadSpec.scala @@ -13,21 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -/** - * Copyright (C) 2013-2018 Expedia Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ + package com.hotels.styx.proxy import java.io.{File, IOException, RandomAccessFile} @@ -36,10 +22,9 @@ import com.google.common.base.Charsets.UTF_8 import com.google.common.io.Files import com.google.common.io.Files._ import com.hotels.styx.MockServer.responseSupplier +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.FullHttpResponse.response import com.hotels.styx.api.HttpHeaderNames.HOST -import com.hotels.styx.api.HttpRequest -import com.hotels.styx.api.messages.HttpMethod._ import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.support.configuration.{HttpBackend, Origins} import com.hotels.styx.{DefaultStyxConfiguration, MockServer, StyxProxySpec} @@ -79,7 +64,7 @@ class BigFileDownloadSpec extends FunSpec ignore("Big file requests") { it("should proxy big file requests") { - val req = new HttpRequest.Builder(GET, "/download") + val req = get("/download") .addHeader(HOST, styxServer.proxyHost) .build() diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ChunkedDownloadSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ChunkedDownloadSpec.scala index 962deab197..994b7554ce 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ChunkedDownloadSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ChunkedDownloadSpec.scala @@ -33,7 +33,7 @@ import io.netty.handler.codec.http.LastHttpContent.EMPTY_LAST_CONTENT import io.netty.handler.codec.http._ import org.scalatest.FunSpec import org.scalatest.concurrent.Eventually - +import com.hotels.styx.api.FullHttpRequest.get import scala.concurrent.duration.{Duration, _} @@ -63,7 +63,7 @@ class ChunkedDownloadSpec extends FunSpec it("Proxies a response with chunked HTTP content.") { originRespondingWith(response200OkWithThreeChunks("a" * 10, "b" * 20, "c" * 30)) - val request = api.HttpRequest.get(styxServer.routerURL("/chunkedDownloadSpec/1")).build() + val request = get(styxServer.routerURL("/chunkedDownloadSpec/1")).build() val response = decodedRequest(request) response.status() should be(OK) @@ -76,7 +76,7 @@ class ChunkedDownloadSpec extends FunSpec val messageBody = "Foo bar 0123456789012345678901234567890123456789\\n" * 100 originRespondingWith(response200OkWithSlowChunkedMessageBody(messageBody)) - val request = api.HttpRequest.get(styxServer.routerURL("/chunkedDownloadSpec/2")).build() + val request = get(styxServer.routerURL("/chunkedDownloadSpec/2")).build() val response = decodedRequest(request) response.status() should be(OK) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeaderNamesSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeaderNamesSpec.scala index 93a6a72c70..159253f197 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeaderNamesSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeaderNamesSpec.scala @@ -16,19 +16,17 @@ package com.hotels.styx.proxy import com.github.tomakehurst.wiremock.client.WireMock._ -import com.hotels.styx.{MockServer, StyxConfiguration, StyxProxySpec} -import com.hotels.styx.api.HttpRequest -import com.hotels.styx.api.support.HostAndPorts.freePort +import com.hotels.styx.api.FullHttpRequest.get +import com.hotels.styx.api.HttpHeaderNames.HOST +import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} import com.hotels.styx.support.matchers.IsOptional.matches import com.hotels.styx.support.matchers.RegExMatcher.matchesRegex -import com.hotels.styx.api.HttpHeaderNames.HOST -import com.hotels.styx.api.messages.HttpMethod.GET +import com.hotels.styx.{MockServer, StyxConfiguration, StyxProxySpec} import org.hamcrest.MatcherAssert.assertThat -import org.scalatest.{BeforeAndAfter, FunSpec} -import com.hotels.styx.api.messages.HttpResponseStatus._ import org.hamcrest.Matchers.is +import org.scalatest.{BeforeAndAfter, FunSpec} /** * @@ -62,7 +60,7 @@ class HeaderNamesSpec extends FunSpec } describe("Proxied responses have expected headers added") { it("should add response headers") { - val req = new HttpRequest.Builder(GET, "/") + val req = get("/") .addHeader(HOST, styxServer.proxyHost) .build() val resp = decodedRequest(req) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeadersSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeadersSpec.scala index 9f4a966cb5..bfdd78bad4 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeadersSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HeadersSpec.scala @@ -15,14 +15,14 @@ */ package com.hotels.styx.proxy -import com.hotels.styx.api.messages.HttpResponseStatus._ import _root_.io.netty.handler.codec.http.HttpHeaders.Names.{UPGRADE, _} import _root_.io.netty.handler.codec.http.HttpHeaders.Values._ -import _root_.io.netty.handler.codec.http.HttpMethod._ -import com.hotels.styx.api.messages.HttpMethod.GET import com.github.tomakehurst.wiremock.client.WireMock._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.HttpCookieAttribute.{domain, httpOnly, path} -import com.hotels.styx.api._ +import com.hotels.styx.api.HttpHeaderNames.X_FORWARDED_FOR +import com.hotels.styx.api.messages.HttpResponseStatus._ +import com.hotels.styx.api.{HttpCookie, HttpHeaderValues} import com.hotels.styx.support.NettyOrigins import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins} @@ -64,7 +64,7 @@ class HeadersSpec extends FunSpec describe("Headers handling") { it("should pass through most http headers to the backend") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .addHeader("Foo", "bar") .addHeader("User-Agent", "Styx/1.0") @@ -81,7 +81,7 @@ class HeadersSpec extends FunSpec } it("should not add a default User-Agent if there isn't one in the request") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -96,7 +96,7 @@ class HeadersSpec extends FunSpec describe("setting host header") { it("it should set the host if missing") { - val req = new HttpRequest.Builder(GET, s"http://localhost:${recordingBackend.port()}/headers") + val req = get(s"http://localhost:${recordingBackend.port()}/headers") .build() val resp = decodedRequest(req) @@ -108,7 +108,7 @@ class HeadersSpec extends FunSpec } it("should use host and port from an absolute URI to override the Host header") { - val req = new HttpRequest.Builder(GET, s"http://localhost:${recordingBackend.port()}/headers") + val req = get(s"http://localhost:${recordingBackend.port()}/headers") .addHeader(HOST, "www.example.com") .build() @@ -125,7 +125,7 @@ class HeadersSpec extends FunSpec describe("setting to X-Forwarded-For header") { it("should add the client IP to X-Forwarded-For") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -134,14 +134,14 @@ class HeadersSpec extends FunSpec assert(resp.status() == OK) recordingBackend.verify(getRequestedFor(urlPathEqualTo("/headers")) - .withHeader(HttpHeaderNames.X_FORWARDED_FOR.toString, equalTo("127.0.0.1"))) + .withHeader(X_FORWARDED_FOR.toString, equalTo("127.0.0.1"))) } it("should append the client IP to X-Forwarded-For") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) - .addHeader(HttpHeaderNames.X_FORWARDED_FOR, "10.9.8.7") + .addHeader(X_FORWARDED_FOR, "10.9.8.7") .build() val resp = decodedRequest(req) @@ -149,7 +149,7 @@ class HeadersSpec extends FunSpec assert(resp.status() == OK) recordingBackend.verify(getRequestedFor(urlPathEqualTo("/headers")) - .withHeader(HttpHeaderNames.X_FORWARDED_FOR.toString, equalTo("10.9.8.7, 127.0.0.1"))) + .withHeader(X_FORWARDED_FOR.toString, equalTo("10.9.8.7, 127.0.0.1"))) } } @@ -157,7 +157,7 @@ class HeadersSpec extends FunSpec describe("setting VIA header") { it("should add itself to the Via request header for an HTTP/1.1 request") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -170,7 +170,7 @@ class HeadersSpec extends FunSpec } it("should append itself to the Via request header for an HTTP/1.1 request") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .addHeader(VIA, "1.1 apache") .build() @@ -184,7 +184,7 @@ class HeadersSpec extends FunSpec } it("should add itself to the Via response heaver") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -196,7 +196,7 @@ class HeadersSpec extends FunSpec recordingBackend.stub(urlPathEqualTo("/headers"), aResponse.withStatus(200) .withHeader(VIA, "1.1 apache")) - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -211,7 +211,7 @@ class HeadersSpec extends FunSpec describe("hop by hop headers") { it("should remove hop by hop headers, apart from Transfer-Encoding, from request") { - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .header(HOST, styxServer.proxyHost) .header("Keep-Alive", "true") .header(PROXY_AUTHENTICATE, "true") @@ -241,7 +241,7 @@ class HeadersSpec extends FunSpec ) - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -260,7 +260,7 @@ class HeadersSpec extends FunSpec it("should remove all fields from request indicated by Connection header value") { - val req = HttpRequest.get("/headers") + val req = get("/headers") .header(HOST, styxServer.proxyHost) .addHeader(CONNECTION, "Foo, Bar, Baz") .addHeader("Foo", "abc") @@ -294,7 +294,7 @@ class HeadersSpec extends FunSpec .withHeader(UPGRADE, "foo") ) - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -317,7 +317,7 @@ class HeadersSpec extends FunSpec .withHeader(CONTENT_LENGTH, "60") ) - val req = new HttpRequest.Builder(GET, "/headers") + val req = get("/headers") .addHeader(HOST, styxServer.proxyHost) .build() @@ -333,7 +333,7 @@ class HeadersSpec extends FunSpec responseWithHeaders( HttpHeader(CONTENT_LENGTH, "50, 60"))) - val req = new HttpRequest.Builder(GET, "/badheaders") + val req = get("/badheaders") .addHeader(HOST, styxServer.proxyHost) .build() @@ -347,7 +347,7 @@ class HeadersSpec extends FunSpec responseWithHeaders( HttpHeader(CONTENT_LENGTH, "50, 50"))) - val req = new HttpRequest.Builder(GET, "/badheaders") + val req = get("/badheaders") .addHeader(HOST, styxServer.proxyHost) .build() @@ -362,7 +362,7 @@ class HeadersSpec extends FunSpec HttpHeader(CONTENT_LENGTH, "50"), HttpHeader(TRANSFER_ENCODING, CHUNKED))) - val req = new HttpRequest.Builder(GET, "/badheaders") + val req = get("/badheaders") .addHeader(HOST, styxServer.proxyHost) .build() @@ -385,7 +385,7 @@ class HeadersSpec extends FunSpec "/badheaders" -> HttpBackend("app-1", Origins(originOne)) ) - val req = new HttpRequest.Builder(GET, "/quotedCookies") + val req = get("/quotedCookies") .addHeader(HOST, styxServer.proxyHost) .addCookie("test-cookie", "\"hu_hotels_com,HCOM_HU,hu_HU,\"") .build() @@ -409,7 +409,7 @@ class HeadersSpec extends FunSpec "/badheaders" -> HttpBackend("app-1", Origins(originOne)) ) - val req = new HttpRequest.Builder(GET, "/cookies") + val req = get("/cookies") .addHeader(HOST, styxServer.proxyHost) .build() diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpMessageLoggingSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpMessageLoggingSpec.scala index 44fc71258f..5383b5887f 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpMessageLoggingSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpMessageLoggingSpec.scala @@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import ch.qos.logback.classic.Level._ import com.github.tomakehurst.wiremock.client.WireMock.{get => _, _} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.client.StyxHeaderConfig.ORIGIN_ID_DEFAULT import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer @@ -131,7 +131,7 @@ class HttpMessageLoggingSpec extends FunSpec assertThat(logger.log.size(), is(2)) assertThat(logger.log(), hasItem(loggingEvent(INFO, - "requestId=[-a-z0-9]+, request=\\{method=GET, secure=true, uri=/foobar, origin=\"N/A\", headers=.*, cookies=\\[\\]}"))) + "requestId=[-a-z0-9]+, request=\\{method=GET, secure=true, uri=https://localhost:[0-9]+/foobar, origin=\"N/A\", headers=.*, cookies=\\[\\]}"))) assertThat(logger.log(), hasItem(loggingEvent(INFO, "requestId=[-a-z0-9]+, response=\\{status=200 OK, headers=\\[Server=Jetty\\(6.1.26\\), " + ORIGIN_ID_DEFAULT + "=generic-app-01, Via=1.1 styx\\], cookies=\\[\\]\\}"))) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpOutboundMessageLoggingSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpOutboundMessageLoggingSpec.scala index f988801891..fb7f4b8a97 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpOutboundMessageLoggingSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/HttpOutboundMessageLoggingSpec.scala @@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import ch.qos.logback.classic.Level._ import com.github.tomakehurst.wiremock.client.WireMock.{get => _, _} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration._ diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/LoggingSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/LoggingSpec.scala index 4fe18c4ab5..9286cfaa85 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/LoggingSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/LoggingSpec.scala @@ -20,13 +20,12 @@ import java.nio.charset.StandardCharsets.UTF_8 import ch.qos.logback.classic.Level._ import com.github.tomakehurst.wiremock.client.WireMock.{get => _, _} import com.hotels.styx.api.HttpInterceptor.Chain -import com.hotels.styx.api.HttpRequest._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.INTERNAL_SERVER_ERROR import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.api.metrics.HttpErrorStatusCauseLogger import com.hotels.styx.api.plugins.spi.PluginException import com.hotels.styx.api.{HttpRequest, HttpResponse, StyxObservable} -import com.hotels.styx.support.api.BlockingObservables.waitForResponse import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} import com.hotels.styx.support.matchers.LoggingEventMatcher._ @@ -97,7 +96,7 @@ class LoggingSpec extends FunSpec .addHeader(X_THROW_AT, AT_REQUEST) .build() - val response = waitForResponse(client.sendRequest(request)) + val response = decodedRequest(request) assertThat(response.status(), is(INTERNAL_SERVER_ERROR)) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginRestrictionSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginRestrictionSpec.scala index 190301a9a7..04cb8e4084 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginRestrictionSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginRestrictionSpec.scala @@ -17,7 +17,7 @@ package com.hotels.styx.proxy import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx.api.HttpHeaderNames._ -import com.hotels.styx.api.HttpRequest +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.client.StyxHeaderConfig.ORIGIN_ID_DEFAULT import com.hotels.styx.support.backends.FakeHttpServer @@ -52,7 +52,7 @@ class OriginRestrictionSpec extends FunSpec describe("Routes correctly") { it("Routes to origin indicated by cookie.") { - val request = HttpRequest.get("/app/") + val request = get("/app/") .header(HOST, styxServer.proxyHost) .addCookie("originRestrictionCookie", "h2") .build() @@ -64,7 +64,7 @@ class OriginRestrictionSpec extends FunSpec } it("Routes to range of origins indicated by cookie.") { - val request = HttpRequest.get("/app/") + val request = get("/app/") .header(HOST, styxServer.proxyHost) .addCookie("originRestrictionCookie", "h(2|3)") .build() @@ -75,7 +75,7 @@ class OriginRestrictionSpec extends FunSpec } it("If nothing matches treat as no hosts available") { - val request = HttpRequest.get("/app/") + val request = get("/app/") .header(HOST, styxServer.proxyHost) .addCookie("originRestrictionCookie", "(?!)") .build() @@ -86,7 +86,7 @@ class OriginRestrictionSpec extends FunSpec } it("Routes to list of origins indicated by cookie.") { - val request = HttpRequest.get("/app/") + val request = get("/app/") .header(HOST, styxServer.proxyHost) .addCookie("originRestrictionCookie", "h2,h[3-4]") .build() diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsConnectionSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsConnectionSpec.scala index 7c5a23e85c..e3d1f7d9d1 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsConnectionSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsConnectionSpec.scala @@ -18,10 +18,9 @@ package com.hotels.styx.proxy import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock.{aResponse, post => wmpost} -import com.hotels.styx.api.HttpRequest.post +import com.hotels.styx.api.FullHttpRequest.post import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.client.StyxHttpClient -import com.hotels.styx.support.api.BlockingObservables.waitForResponse import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins} import com.hotels.styx.support.matchers.LoggingTestSupport @@ -63,7 +62,7 @@ class OriginsConnectionSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = waitForResponse(client.sendRequest(request)) + val response = decodedRequest(request) response.status() should be(OK) response.bodyAs(UTF_8) should be("") @@ -85,7 +84,7 @@ class OriginsConnectionSpec extends FunSpec .addHeader("Content-Length", "0") .build() - val response = waitForResponse(client.sendRequest(request)) + val response = decodedRequest(request) response.status() should be(NO_CONTENT) response.bodyAs(UTF_8) should be("") diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadRepetitionSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadRepetitionSpec.scala index 7aa3c45aad..5a5a369056 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadRepetitionSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadRepetitionSpec.scala @@ -17,7 +17,7 @@ package com.hotels.styx.proxy import java.nio.charset.StandardCharsets.UTF_8 -import com.hotels.styx.api.HttpRequest +import com.hotels.styx.api.FullHttpRequest import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins} import com.hotels.styx.{DefaultStyxConfiguration, StyxClientSupplier, StyxProxySpec} @@ -94,6 +94,6 @@ class OriginsReloadRepetitionSpec extends FunSpec } private def get(url: String) = { - decodedRequest(HttpRequest.get(url).build()) + decodedRequest(FullHttpRequest.get(url).build()) } } diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadSpec.scala index a9a4e8997b..5acc99f072 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/OriginsReloadSpec.scala @@ -17,7 +17,7 @@ package com.hotels.styx.proxy import java.nio.charset.StandardCharsets.UTF_8 -import com.hotels.styx.api.HttpRequest +import com.hotels.styx.api.FullHttpRequest import com.hotels.styx.api.messages.HttpResponseStatus.{METHOD_NOT_ALLOWED, OK} import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins} @@ -95,10 +95,10 @@ class OriginsReloadSpec extends FunSpec } private def post(url: String, content: String = "") = { - decodedRequest(HttpRequest.post(url).body(content).build()) + decodedRequest(FullHttpRequest.post(url).body(content, UTF_8).build()) } private def get(url: String) = { - decodedRequest(HttpRequest.get(url).build()) + decodedRequest(FullHttpRequest.get(url).build()) } } diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ProxySpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ProxySpec.scala index cd0a374271..ec46e9d7b0 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ProxySpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ProxySpec.scala @@ -17,23 +17,19 @@ package com.hotels.styx.proxy import java.nio.charset.StandardCharsets.UTF_8 -import com.github.tomakehurst.wiremock.client.RequestPatternBuilder +import com.github.tomakehurst.wiremock.client.{RequestPatternBuilder, WireMock} import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx.MockServer.responseSupplier +import com.hotels.styx.api.FullHttpRequest.get +import com.hotels.styx.api.FullHttpRequest.head import com.hotels.styx.api.HttpHeaderNames._ -import com.hotels.styx.api.HttpRequest.Builder import com.hotels.styx.api.HttpResponse.response -import com.hotels.styx.api.messages.HttpMethod.{GET, HEAD} import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.api.messages.HttpVersion._ import com.hotels.styx.api.support.HostAndPorts._ -import com.hotels.styx.api.{FullHttpResponse, HttpClient, HttpRequest} -import com.hotels.styx.client.HttpConfig.newHttpConfigBuilder -import com.hotels.styx.client.HttpRequestOperationFactory.Builder.httpRequestOperationFactoryBuilder +import com.hotels.styx.api.{FullHttpClient, FullHttpResponse} import com.hotels.styx.client.StyxHeaderConfig.STYX_INFO_DEFAULT -import com.hotels.styx.client.connectionpool.CloseAfterUseConnectionDestination.Factory -import com.hotels.styx.client.netty.connectionpool.NettyConnectionFactory -import com.hotels.styx.client.{ConnectionSettings, SimpleNettyHttpClient} +import com.hotels.styx.client.{ConnectionSettings, SimpleHttpClient} import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origin, Origins} import com.hotels.styx.support.matchers.IsOptional.{isValue, matches} @@ -43,6 +39,10 @@ import com.hotels.styx.{DefaultStyxConfiguration, MockServer, StyxProxySpec} import org.hamcrest.MatcherAssert.assertThat import org.scalatest.{BeforeAndAfter, FunSpec} +import scala.compat.java8.FutureConverters.CompletionStageOps +import scala.concurrent.Await +import scala.concurrent.duration._ + class ProxySpec extends FunSpec with StyxProxySpec with DefaultStyxConfiguration @@ -80,7 +80,7 @@ class ProxySpec extends FunSpec .withBody("bodyContent") ) - val req = new HttpRequest.Builder(GET, "/") + val req = get("/") .addHeader(HOST, styxServer.proxyHost) .build() @@ -104,7 +104,7 @@ class ProxySpec extends FunSpec mockServer.stub("/http10", responseSupplier(() => response().build())) - val req = new HttpRequest.Builder(GET, "/http10") + val req = get("/http10") .addHeader(HOST, styxServer.proxyHost) .build() @@ -119,24 +119,21 @@ class ProxySpec extends FunSpec describe("Handling responses without body") { recordingBackend .stub(urlPathEqualTo("/bodiless"), aResponse.withStatus(200)) - .stub(head(urlPathEqualTo("/bodiless")), aResponse.withStatus(200)) + .stub(WireMock.head(urlPathEqualTo("/bodiless")), aResponse.withStatus(200)) it("should respond to HEAD with bodiless response") { - val client: HttpClient = new SimpleNettyHttpClient.Builder() - .connectionDestinationFactory(new Factory() - .connectionSettings(new ConnectionSettings(1000)) - .connectionFactory(new NettyConnectionFactory.Builder() - .name("scalatest-e2e-client") - .httpConfig(newHttpConfigBuilder().setMaxHeadersSize(2 * 8192).build()) - .httpRequestOperationFactory(httpRequestOperationFactoryBuilder().build()) - .build())).build() + val client: FullHttpClient = new SimpleHttpClient.Builder() + .connectionSettings(new ConnectionSettings(1000)) + .maxHeaderSize(2 * 8192) + .threadName("scalatest-e2e-client") + .build() - val req = new HttpRequest.Builder(HEAD, "/bodiless") + val req = head("/bodiless") .addHeader(HOST, styxServer.proxyHost) .build() - val resp = decodedRequestWithClient(client, req) + val resp = Await.result(client.sendRequest(req).toScala, 5.seconds) recordingBackend.verify(headRequestedFor(urlPathEqualTo("/bodiless"))) @@ -148,7 +145,7 @@ class ProxySpec extends FunSpec recordingBackend .stub(urlPathEqualTo("/204"), aResponse.withStatus(204).withBody("I should not be here")) - val request = new Builder(GET, "/204") + val request = get("/204") .addHeader(HOST, styxServer.proxyHost) .build() @@ -162,7 +159,7 @@ class ProxySpec extends FunSpec recordingBackend .stub(urlPathEqualTo("/304"), aResponse.withStatus(304).withBody("I should not be here")) - val request = new Builder(GET, "/304") + val request = get("/304") .addHeader(HOST, styxServer.proxyHost) .build() @@ -179,7 +176,7 @@ class ProxySpec extends FunSpec "/unavailable" -> HttpBackend("http10", Origins(Origin("localhost", freePort(), "app-1-01"))) ) - val req = new Builder(GET, "/unavailable") + val req = get("/unavailable") .addHeader(HOST, styxServer.proxyHost) .build() @@ -192,7 +189,7 @@ class ProxySpec extends FunSpec it("should return a 502 BAD_GATEWAY if a backend service is not configured") { styxServer.setBackends() - val req = new Builder(GET, "/nonexistant-service") + val req = get("/nonexistant-service") .addHeader(HOST, styxServer.proxyHost) .build() @@ -210,7 +207,7 @@ class ProxySpec extends FunSpec .stub(urlStartingWith("/url"), aResponse.withStatus(200)) it("should substitute URL path according to configuration") { - val req = new Builder(GET, "/url/search.do?resolved-location=CITY%3A549499%3APROVIDED%3APROVIDED&destination-id=549499&q-destination=London%2C%20England%2C%20United%20Kingdom&q-rooms=1&q-room-0-adults=2&q-room-0-children=0") + val req = get("/url/search.do?resolved-location=CITY%3A549499%3APROVIDED%3APROVIDED&destination-id=549499&q-destination=London%2C%20England%2C%20United%20Kingdom&q-rooms=1&q-room-0-adults=2&q-room-0-children=0") .addHeader(HOST, styxServer.proxyHost) .build() @@ -219,7 +216,7 @@ class ProxySpec extends FunSpec } it("should encode the path") { - val req = new Builder(GET, "/url/lp/de408991/%D7%9E%D7%9C%D7%95%D7%A0%D7%95%D7%AA-%D7%A7%D7%95%D7%A4%D7%A0%D7%94%D7%92%D7%9F-%D7%93%D7%A0%D7%9E%D7%A8%D7%A7/") + val req = get("/url/lp/de408991/%D7%9E%D7%9C%D7%95%D7%A0%D7%95%D7%AA-%D7%A7%D7%95%D7%A4%D7%A0%D7%94%D7%92%D7%9F-%D7%93%D7%A0%D7%9E%D7%A8%D7%A7/") .addHeader(HOST, styxServer.proxyHost) .build() @@ -228,7 +225,7 @@ class ProxySpec extends FunSpec } it("should pass url with allowed chars in the path without encoding") { - val req = new Builder(GET, "/url/newsletter/subscribe.html;sessid=lUmrydZOJM85gj5BliH_qVcl-V.noJvmRouteSet") + val req = get("/url/newsletter/subscribe.html;sessid=lUmrydZOJM85gj5BliH_qVcl-V.noJvmRouteSet") .addHeader(HOST, styxServer.proxyHost) .build() diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ResponseInfoHeaderSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ResponseInfoHeaderSpec.scala index f4d4016ee8..e14aece45f 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ResponseInfoHeaderSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/ResponseInfoHeaderSpec.scala @@ -16,9 +16,8 @@ package com.hotels.styx.proxy import com.github.tomakehurst.wiremock.client.WireMock._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.HttpHeaderNames._ -import com.hotels.styx.api.HttpRequest -import com.hotels.styx.api.messages.HttpMethod.GET import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.client.StyxHeaderConfig.STYX_INFO_DEFAULT import com.hotels.styx.support.backends.FakeHttpServer @@ -53,7 +52,7 @@ class VersionPresentInResponseHeaderSpec extends FunSpec } describe("Styx Info response header configured to contain version") { it("should respond with version in response header") { - val req = new HttpRequest.Builder(GET, "/") + val req = get("/") .addHeader(HOST, styxServer.proxyHost) .build() val resp = decodedRequest(req) @@ -84,7 +83,7 @@ class VersionAbsentFromResponseHeaderSpec extends FunSpec describe("Styx Info response header default format") { it("should respond without version in response header") { - val req = new HttpRequest.Builder(GET, "/") + val req = get("/") .addHeader(HOST, styxServer.proxyHost) .build() val resp = decodedRequest(req) diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/TimeoutsSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/TimeoutsSpec.scala index e6fda3b807..4a81993b4c 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/TimeoutsSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/TimeoutsSpec.scala @@ -15,31 +15,27 @@ */ package com.hotels.styx.proxy -import java.util.concurrent.TimeUnit.MILLISECONDS +import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ -import com.hotels.styx.api.HttpHeaderNames._ -import com.hotels.styx.api.messages.HttpResponseStatus._ -import com.hotels.styx.api.{FullHttpResponse, HttpRequest, HttpResponse, StyxInternalObservables} +import com.hotels.styx.StyxProxySpec import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.TestClientSupport -import com.hotels.styx.support.api.BlockingObservables.waitForResponse import com.hotels.styx.support.backends.FakeHttpServer -import com.hotels.styx.support.configuration.{HttpBackend, Origins, ProxyConfig, StyxConfig} -import com.hotels.styx.{StyxClientSupplier, StyxProxySpec} -import io.netty.buffer.ByteBuf +import com.hotels.styx.support.configuration._ import io.netty.buffer.Unpooled.copiedBuffer -import com.hotels.styx.api.messages.HttpMethod.GET +import io.netty.handler.codec.http.HttpHeaderNames.{CONTENT_LENGTH, CONTENT_TYPE, HOST} +import io.netty.handler.codec.http.HttpResponseStatus.{GATEWAY_TIMEOUT, REQUEST_TIMEOUT} +import io.netty.handler.codec.http.HttpVersion.HTTP_1_1 +import io.netty.handler.codec.http._ import org.scalatest.FunSpec import org.scalatest.concurrent.Eventually -import rx.Observable import scala.concurrent.duration._ class TimeoutsSpec extends FunSpec with StyxProxySpec with TestClientSupport - with StyxClientSupplier with Eventually { val normalBackend = FakeHttpServer.HttpStartupConfig().start() @@ -77,67 +73,50 @@ class TimeoutsSpec extends FunSpec describe("Request timeouts") { it("should log and return 408 Request Timeout when client does not send a full HTTP request within configurable time.") { - val delayedRequestBody: Observable[ByteBuf] = Observable.just(copiedBuffer("content".getBytes())) - .delay(styxConfig.proxyConfig.requestTimeoutMillis, MILLISECONDS) + val testClient = aggregatingTestClient("localhost", styxServer.httpPort) - val slowRequest = new HttpRequest.Builder(GET, "/backends") - .header(HOST, styxServer.proxyHost) - .header(CONTENT_TYPE, "text/html; charset=UTF-8") - .header(CONTENT_LENGTH, "500") - .body(StyxInternalObservables.fromRxObservable(delayedRequestBody)) - .build() + val response = withTestClient(testClient) { - val resp = decodedRequest(slowRequest, debug = true) + val slowRequest = new DefaultHttpRequest(HTTP_1_1, HttpMethod.GET, "/backends") + slowRequest.headers().add(HOST, styxServer.proxyHost) + slowRequest.headers().add(CONTENT_TYPE, "text/html; charset=UTF-8") + slowRequest.headers().add(CONTENT_LENGTH, "500") - assert(resp.status() == REQUEST_TIMEOUT) + testClient.write(slowRequest) + testClient.write(new DefaultHttpContent(copiedBuffer("xys", UTF_8))) + + val response = testClient.waitForResponse().asInstanceOf[FullHttpResponse] + + assert(response.status() == REQUEST_TIMEOUT) + } } } describe("Response timeouts") { - it("should return a 504 if a backend takes longer than the configured response timeout to start returning a response") { - val req = new HttpRequest.Builder(GET, "/slowResponseHeader") - .addHeader(HOST, styxServer.proxyHost) - .build() - - val transaction = client.sendRequest(req) - val (resp, responseTime) = responseAndResponseTime(transaction) - - slowBackend.verify(getRequestedFor(urlPathEqualTo("/slowResponseHeader"))) - - assert(resp.status() == GATEWAY_TIMEOUT) - assert(responseTime > responseTimeout) - } + val testClient = aggregatingTestClient("localhost", styxServer.httpPort) - ignore("should still return the response if the body takes longer than the header timeout") { - val req = new HttpRequest.Builder(GET, "/slowResponseBody") - .addHeader(HOST, styxServer.proxyHost) - .build() + withTestClient(testClient) { - val resp = decodedRequest(req) + val slowRequest = new DefaultFullHttpRequest(HTTP_1_1, HttpMethod.GET, "/slowResponseHeader") + slowRequest.headers().add(HOST, styxServer.proxyHost) - slowBackend.verify(getRequestedFor(urlPathEqualTo("/slowResponseBody"))) + testClient.write(slowRequest) - assert(resp.status() == OK) + val responseTime = time { + val response = testClient.waitForResponse().asInstanceOf[FullHttpResponse] + assert(response.status() == GATEWAY_TIMEOUT) + } + assert(responseTime > responseTimeout) + } } } - } - - def responseAndResponseTime(transaction: Observable[HttpResponse]): (FullHttpResponse, Long) = { - var response = FullHttpResponse.response().build() - val duration = time { - response = waitForResponse(transaction) + def time[A](codeBlock: => A) = { + val s = System.nanoTime + codeBlock + ((System.nanoTime - s) / 1e6).asInstanceOf[Int] } - (response, duration) - } - - - def time[A](codeBlock: => A) = { - val s = System.nanoTime - codeBlock - ((System.nanoTime - s) / 1e6).asInstanceOf[Int] } - -} +} \ No newline at end of file diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/UnwiseCharactersSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/UnwiseCharactersSpec.scala index 7dc47dc769..d49a97ef1a 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/UnwiseCharactersSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/UnwiseCharactersSpec.scala @@ -19,9 +19,8 @@ import ch.qos.logback.classic.Level._ import com.github.tomakehurst.wiremock.client.RequestPatternBuilder import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx._ +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.HttpHeaderNames.HOST -import com.hotels.styx.api.HttpRequest -import com.hotels.styx.api.messages.HttpMethod.GET import com.hotels.styx.proxy.encoders.ConfigurableUnwiseCharsEncoder import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.{HttpBackend, Origins, StyxConfig} @@ -60,7 +59,7 @@ class UnwiseCharactersSpec extends FunSpec with StyxProxySpec { it("Should escape all unwise characters in URL as per styx configuration") { val logger = new LoggingTestSupport(classOf[ConfigurableUnwiseCharsEncoder]) - val req = new HttpRequest.Builder(GET, "/url/unwiseQQblah") + val req = get("/url/unwiseQQblah") .header(HOST, styxServer.proxyHost) .build() diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/EmptyTlsProtocolsListSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/EmptyTlsProtocolsListSpec.scala index 357c5fcd08..fae2f8a85f 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/EmptyTlsProtocolsListSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/EmptyTlsProtocolsListSpec.scala @@ -16,9 +16,9 @@ package com.hotels.styx.proxy.https import com.github.tomakehurst.wiremock.client.WireMock._ -import com.hotels.styx.api.client.UrlConnectionHttpClient import com.hotels.styx.api.messages.HttpResponseStatus.OK -import com.hotels.styx.api.{HttpClient, HttpRequest} +import com.hotels.styx.api.{FullHttpClient, FullHttpRequest} +import com.hotels.styx.client.SimpleHttpClient import com.hotels.styx.infrastructure.HttpResponseImplicits import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer @@ -27,6 +27,8 @@ import com.hotels.styx.{SSLSetup, StyxProxySpec} import io.netty.handler.codec.http.HttpHeaders.Names._ import org.scalatest.{FunSpec, ShouldMatchers} +import scala.concurrent.Await + class EmptyTlsProtocolsListSpec extends FunSpec with StyxProxySpec with HttpResponseImplicits @@ -35,8 +37,8 @@ class EmptyTlsProtocolsListSpec extends FunSpec val crtFile = fixturesHome(this.getClass, "/ssl/testCredentials.crt").toString val keyFile = fixturesHome(this.getClass, "/ssl/testCredentials.key").toString - val clientV12 = newClient("TLSv1.2") - val clientV11 = newClient("TLSv1.1") + val clientV12 : FullHttpClient = newClient(Seq("TLSv1.2")) + val clientV11 : FullHttpClient = newClient(Seq("TLSv1.1")) override val styxConfig = StyxConfig( ProxyConfig( @@ -65,25 +67,30 @@ class EmptyTlsProtocolsListSpec extends FunSpec super.afterAll() } + import scala.concurrent.duration._ + import scala.compat.java8.FutureConverters.CompletionStageOps + describe("Empty TLS protocols list") { recordingBackend.stub(urlPathEqualTo("/secure"), aResponse.withStatus(OK.code())) it("Empty TLS protocols list activates all supported protocols") { - val req = HttpRequest.get(styxServer.secureRouterURL("/secure")) + val req = FullHttpRequest.get(styxServer.secureRouterURL("/secure")) .header(HOST, styxServer.httpsProxyHost) .secure(true) .build() - val resp1 = decodedRequestWithClient(clientV11, req) + val resp1 = Await.result(clientV11.sendRequest(req).toScala, 3.seconds) resp1.status() should be(OK) - val resp2 = decodedRequestWithClient(clientV12, req) + val resp2 = Await.result(clientV12.sendRequest(req).toScala, 3.seconds) resp2.status() should be(OK) } } - def newClient(supportedProtocols: String): HttpClient = { - new UrlConnectionHttpClient(TWO_SECONDS, FIVE_SECONDS, supportedProtocols) + def newClient(supportedProtocols: Seq[String]): FullHttpClient = { + new SimpleHttpClient.Builder() + .tlsSettings(TlsSettings(protocols = supportedProtocols).asJava) + .build() } } diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/HttpsSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/HttpsSpec.scala index e1821b863d..39e3985936 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/HttpsSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/HttpsSpec.scala @@ -16,8 +16,8 @@ package com.hotels.styx.proxy.https import com.github.tomakehurst.wiremock.client.WireMock._ +import com.hotels.styx.api.FullHttpRequest import com.hotels.styx.api.HttpHeaderNames.{X_FORWARDED_PROTO, _} -import com.hotels.styx.api.HttpRequest import com.hotels.styx.api.messages.HttpMethod.GET import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.infrastructure.HttpResponseImplicits @@ -63,7 +63,7 @@ class HttpsSpec extends FunSpec "https-app", Origins(recordingBackend), TlsSettings() )) - val req = new HttpRequest.Builder(GET, styxServer.secureRouterURL("/secure")) + val req = new FullHttpRequest.Builder(GET, styxServer.secureRouterURL("/secure")) .header(HOST, styxServer.httpsProxyHost) .build() diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/ProtocolsSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/ProtocolsSpec.scala index 1b70334ff2..e9bd1d4b27 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/ProtocolsSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/ProtocolsSpec.scala @@ -20,7 +20,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ import com.github.tomakehurst.wiremock.client.{ValueMatchingStrategy, WireMock} import com.hotels.styx.api.HttpHeaderNames.X_FORWARDED_PROTO -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/Tls12Spec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/Tls12Spec.scala index 8fe7f5a397..dbf942a177 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/Tls12Spec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/proxy/https/Tls12Spec.scala @@ -17,10 +17,10 @@ package com.hotels.styx.proxy.https import com.github.tomakehurst.wiremock.client.WireMock._ import com.hotels.styx.api.HttpHeaderNames._ -import com.hotels.styx.api.client.UrlConnectionHttpClient import com.hotels.styx.api.messages.HttpMethod.GET import com.hotels.styx.api.messages.HttpResponseStatus.OK -import com.hotels.styx.api.{HttpClient, HttpRequest} +import com.hotels.styx.api.{FullHttpClient, FullHttpRequest} +import com.hotels.styx.client.SimpleHttpClient import com.hotels.styx.infrastructure.HttpResponseImplicits import com.hotels.styx.support.ResourcePaths.fixturesHome import com.hotels.styx.support.backends.FakeHttpServer @@ -28,6 +28,10 @@ import com.hotels.styx.support.configuration._ import com.hotels.styx.{SSLSetup, StyxProxySpec} import org.scalatest.{FunSpec, ShouldMatchers} +import scala.compat.java8.FutureConverters.CompletionStageOps +import scala.concurrent.Await +import scala.concurrent.duration._ + class Tls12Spec extends FunSpec with StyxProxySpec with HttpResponseImplicits @@ -36,8 +40,8 @@ class Tls12Spec extends FunSpec val crtFile = fixturesHome(classOf[ProtocolsSpec], "/ssl/testCredentials.crt").toString val keyFile = fixturesHome(classOf[ProtocolsSpec], "/ssl/testCredentials.key").toString - val clientV12 = newClient("TLSv1.2") - val clientV11 = newClient("TLSv1.1") + val clientV12 = newClient(Seq("TLSv1.2")) + val clientV11 = newClient(Seq("TLSv1.1")) override val styxConfig = StyxYamlConfig( yamlConfig = @@ -78,30 +82,31 @@ class Tls12Spec extends FunSpec recordingBackend.stub(urlPathEqualTo("/secure"), aResponse.withStatus(200)) it("Accepts TLS 1.2 only") { - val req = new HttpRequest.Builder(GET, styxServer.secureRouterURL("/secure")) + val req = new FullHttpRequest.Builder(GET, styxServer.secureRouterURL("/secure")) .header(HOST, styxServer.httpsProxyHost) .secure(true) .build() - val resp = decodedRequestWithClient(clientV12, req) + val resp = Await.result(clientV12.sendRequest(req).toScala, 3.seconds) resp.status() should be(OK) } it("Refuses TLS 1.1 when TLS 1.2 is required") { - val req = new HttpRequest.Builder(GET, styxServer.secureRouterURL("/secure")) + val req = new FullHttpRequest.Builder(GET, styxServer.secureRouterURL("/secure")) .header(HOST, styxServer.httpsProxyHost) .secure(true) .build() an[RuntimeException] should be thrownBy { - decodedRequestWithClient(clientV11, req) + Await.result(clientV11.sendRequest(req).toScala, 3.seconds) } } } - def newClient(supportedProtocols: String): HttpClient = { - new UrlConnectionHttpClient(TWO_SECONDS, FIVE_SECONDS, supportedProtocols) - } + def newClient(supportedProtocols: Seq[String]): FullHttpClient = + new SimpleHttpClient.Builder() + .tlsSettings(TlsSettings(protocols = supportedProtocols).asJava) + .build() } diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/routing/ConditionRoutingSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/routing/ConditionRoutingSpec.scala index c3dedbb5dd..32089fc21c 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/routing/ConditionRoutingSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/routing/ConditionRoutingSpec.scala @@ -19,7 +19,7 @@ import java.nio.charset.StandardCharsets.UTF_8 import com.github.tomakehurst.wiremock.client.WireMock._ import com.github.tomakehurst.wiremock.client.{ValueMatchingStrategy, WireMock} -import com.hotels.styx.api.HttpRequest.get +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus._ import com.hotels.styx.api.service import com.hotels.styx.infrastructure.{MemoryBackedRegistry, RegistryServiceAdapter} diff --git a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/spi/BackendServiceProviderSpec.scala b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/spi/BackendServiceProviderSpec.scala index a67c197732..a66a28b551 100644 --- a/system-tests/e2e-suite/src/test/scala/com/hotels/styx/spi/BackendServiceProviderSpec.scala +++ b/system-tests/e2e-suite/src/test/scala/com/hotels/styx/spi/BackendServiceProviderSpec.scala @@ -18,7 +18,8 @@ package com.hotels.styx.spi import com.google.common.net.HostAndPort import com.google.common.net.HostAndPort._ import com.hotels.styx.StyxProxySpec -import com.hotels.styx.api.HttpRequest +import com.hotels.styx.api.FullHttpRequest +import com.hotels.styx.api.FullHttpRequest.get import com.hotels.styx.api.messages.HttpResponseStatus.OK import com.hotels.styx.support.backends.FakeHttpServer import com.hotels.styx.support.configuration.StyxConfig @@ -82,8 +83,8 @@ class BackendServiceProviderSpec extends FunSpec with StyxProxySpec { fromParts("localhost", styxServer.httpPort) } - def anHttpRequest: HttpRequest = { - HttpRequest.get(styxServer.routerURL("/pluginPipelineSpec/")).build() + def anHttpRequest: FullHttpRequest = { + get(styxServer.routerURL("/pluginPipelineSpec/")).build() } } diff --git a/system-tests/e2e-testsupport/src/main/java/com/hotels/styx/utils/MetricsSnapshot.java b/system-tests/e2e-testsupport/src/main/java/com/hotels/styx/utils/MetricsSnapshot.java index f270301df3..c2493fd4f9 100644 --- a/system-tests/e2e-testsupport/src/main/java/com/hotels/styx/utils/MetricsSnapshot.java +++ b/system-tests/e2e-testsupport/src/main/java/com/hotels/styx/utils/MetricsSnapshot.java @@ -20,9 +20,9 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableMap; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.HttpResponse; -import com.hotels.styx.api.client.UrlConnectionHttpClient; +import com.hotels.styx.api.FullHttpClient; +import com.hotels.styx.api.FullHttpResponse; +import com.hotels.styx.client.SimpleHttpClient; import java.io.IOException; import java.util.HashMap; @@ -32,12 +32,12 @@ import java.util.Optional; import static com.google.common.base.Preconditions.checkArgument; -import static com.hotels.styx.support.api.HttpMessageBodies.bodyAsString; -import static com.hotels.styx.api.HttpRequest.get; +import static com.hotels.styx.api.FullHttpRequest.get; +import static com.hotels.styx.common.StyxFutures.await; import static java.lang.String.format; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; -import com.hotels.styx.api.HttpRequest; @Deprecated public class MetricsSnapshot { @@ -48,11 +48,9 @@ private MetricsSnapshot(Map tree) { } public static MetricsSnapshot downloadFrom(String host, int port) throws IOException { - HttpClient client = new UrlConnectionHttpClient(1000, 3000); - HttpRequest request = get(format("http://%s:%d/admin/metrics", host, port)).build(); - HttpResponse response = client.sendRequest(request).toBlocking().first(); - String body = bodyAsString(response); - return new MetricsSnapshot(decodeToMap(body)); + FullHttpClient client = new SimpleHttpClient.Builder().build(); + FullHttpResponse response = await(client.sendRequest(get(format("http://%s:%d/admin/metrics", host, port)).build())); + return new MetricsSnapshot(decodeToMap(response.bodyAs(UTF_8))); } public static MetricsSnapshot fromString(String json) throws IOException { diff --git a/system-tests/e2e-testsupport/src/test/java/com/hotels/styx/servers/MockOriginServerTest.java b/system-tests/e2e-testsupport/src/test/java/com/hotels/styx/servers/MockOriginServerTest.java index 82c4d995e7..bfda5d2dac 100644 --- a/system-tests/e2e-testsupport/src/test/java/com/hotels/styx/servers/MockOriginServerTest.java +++ b/system-tests/e2e-testsupport/src/test/java/com/hotels/styx/servers/MockOriginServerTest.java @@ -17,9 +17,10 @@ import com.github.tomakehurst.wiremock.client.ValueMatchingStrategy; import com.github.tomakehurst.wiremock.client.WireMock; +import com.hotels.styx.api.FullHttpClient; import com.hotels.styx.api.FullHttpResponse; -import com.hotels.styx.api.HttpClient; -import com.hotels.styx.api.client.UrlConnectionHttpClient; +import com.hotels.styx.api.service.TlsSettings; +import com.hotels.styx.client.SimpleHttpClient; import com.hotels.styx.server.HttpConnectorConfig; import com.hotels.styx.server.HttpsConnectorConfig; import org.testng.annotations.AfterMethod; @@ -33,8 +34,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor; import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo; import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; -import static com.hotels.styx.api.HttpRequest.get; -import static com.hotels.styx.api.StyxInternalObservables.fromRxObservable; +import static com.hotels.styx.api.FullHttpRequest.get; import static com.hotels.styx.api.messages.HttpResponseStatus.OK; import static com.hotels.styx.api.support.HostAndPorts.freePort; import static com.hotels.styx.common.StyxFutures.await; @@ -44,17 +44,18 @@ import static javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; -import com.hotels.styx.api.HttpRequest; public class MockOriginServerTest { private MockOriginServer server; - private UrlConnectionHttpClient client; + private FullHttpClient client; private HostnameVerifier oldHostNameVerifier; + private SimpleHttpClient tlsClient; @BeforeMethod public void setUp() throws Exception { - client = new UrlConnectionHttpClient(1000, 1000); + client = new SimpleHttpClient.Builder().build(); + tlsClient = new SimpleHttpClient.Builder().tlsSettings(new TlsSettings.Builder().build()).build(); oldHostNameVerifier = disableHostNameVerification(); } @@ -76,10 +77,10 @@ public void configuresEndpoints() throws Exception { .withHeader("a", "b") .withBody("Hello, World!")); - FullHttpResponse response = send(client, + FullHttpResponse response = await(client.sendRequest( get(format("http://localhost:%d/mock", server.port())) .header("X-Forwarded-Proto", "http") - .build()); + .build())); assertThat(response.status(), is(OK)); assertThat(response.header("a"), is(Optional.of("b"))); @@ -104,10 +105,11 @@ public void configuresTlsEndpoints() throws Exception { .withHeader("a", "b") .withBody("Hello, World!")); - FullHttpResponse response = send(client, - get(format("https://localhost:%d/mock", server.port())) - .header("X-Forwarded-Proto", "http") - .build()); + FullHttpResponse response = await( + tlsClient.sendRequest( + get(format("https://localhost:%d/mock", server.port())) + .header("X-Forwarded-Proto", "http") + .build())); assertThat(response.status(), is(OK)); assertThat(response.header("a"), is(Optional.of("b"))); @@ -116,13 +118,6 @@ public void configuresTlsEndpoints() throws Exception { .withHeader("X-Forwarded-Proto", valueMatchingStrategy("http"))); } - - private FullHttpResponse send(HttpClient client, HttpRequest request) { - return await(fromRxObservable(client.sendRequest(request)) - .flatMap(req -> req.toFullResponse(10*1024)) - .asCompletableFuture()); - } - private ValueMatchingStrategy valueMatchingStrategy(String matches) { ValueMatchingStrategy strategy = new ValueMatchingStrategy(); strategy.setMatches(matches);