Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SimpleHttpClient: Use default HTTP/HTTPS ports #188

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
* A client that uses netty as transport.
*/
public final class SimpleHttpClient implements FullHttpClient {
private static final int DEFAULT_HTTPS_PORT = 443;
private static final int DEFAULT_HTTP_PORT = 80;

private final Optional<String> userAgent;
private final ConnectionSettings connectionSettings;
private final int maxResponseSize;
Expand Down Expand Up @@ -84,7 +87,13 @@ private static Origin originFromRequest(FullHttpRequest request) {
.orElseThrow(() -> new IllegalArgumentException("Cannot send request " + request + " as URL is not absolute and no HOST header is present"));
});

return newOriginBuilder(HostAndPort.fromString(hostAndPort)).build();
HostAndPort host = HostAndPort.fromString(hostAndPort);

if (host.getPortOrDefault(-1) < 0) {
host = host.withDefaultPort(request.isSecure() ? DEFAULT_HTTPS_PORT : DEFAULT_HTTP_PORT);
}

return newOriginBuilder(host).build();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
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.Origin;
import com.hotels.styx.api.service.TlsSettings;
import org.mockito.ArgumentCaptor;
import org.testng.annotations.BeforeMethod;
Expand All @@ -36,6 +37,7 @@
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.HttpResponse.response;
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;
Expand All @@ -62,23 +64,23 @@ public void setUp() {
}

@Test
public void sendsHttp() throws IOException {
public void sendsHttp() {
withOrigin(HTTP, port -> {
FullHttpResponse response = await(httpClient().sendRequest(httpRequest(port)));
assertThat(response.status(), is(OK));
});
}

@Test
public void sendsHttps() throws IOException {
public void sendsHttps() {
withOrigin(HTTPS, port -> {
FullHttpResponse response = await(httpsClient().sendRequest(httpsRequest(port)));
assertThat(response.status(), is(OK));
});
}

@Test(expectedExceptions = Exception.class)
public void cannotSendHttpsWhenConfiguredForHttp() throws IOException {
public void cannotSendHttpsWhenConfiguredForHttp() {
withOrigin(HTTPS, port -> {
FullHttpResponse response = await(httpClient().sendRequest(httpsRequest(port)));
assertThat(response.status(), is(OK));
Expand All @@ -93,50 +95,10 @@ public void cannotSendHttpWhenConfiguredForHttps() throws IOException {
});
}

private SimpleHttpClient httpClient() {
return new SimpleHttpClient.Builder()
.build();
}

private SimpleHttpClient httpsClient() {
return new SimpleHttpClient.Builder()
.connectionSettings(new ConnectionSettings(1000))
.tlsSettings(new TlsSettings.Builder()
.authenticate(false)
.build())
.responseTimeoutMillis(6000)
.build();
}

private FullHttpRequest httpRequest(int port) {
return get("http://localhost:" + port)
.header(HOST, "localhost:" + port)
.build();
}

private FullHttpRequest httpsRequest(int port) {
return get("https://localhost:" + port)
.header(HOST, "localhost:" + port)
.build();
}

private void withOrigin(Protocol protocol, IntConsumer portConsumer) {
WireMockServer server = new WireMockServer(wireMockConfig().dynamicPort().dynamicHttpsPort());

try {
server.start();
int port = protocol == HTTP ? server.port() : server.httpsPort();
server.stubFor(WireMock.get(urlStartingWith("/")).willReturn(aResponse().withStatus(200)));
portConsumer.accept(port);
} finally {
server.stop();
}
}

@Test
public void willNotSetAnyUserAgentIfNotSpecified() {
Connection mockConnection = mock(Connection.class);
when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(HttpResponse.response().build()));
when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(response().build()));

SimpleHttpClient client = new SimpleHttpClient.Builder()
.setConnectionFactory((origin, connectionSettings) -> Observable.just(mockConnection))
Expand All @@ -152,7 +114,7 @@ public void willNotSetAnyUserAgentIfNotSpecified() {
@Test
public void setsTheSpecifiedUserAgentWhenSpecified() {
Connection mockConnection = mock(Connection.class);
when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(HttpResponse.response().build()));
when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(response().build()));

SimpleHttpClient client = new SimpleHttpClient.Builder()
.setConnectionFactory((origin, connectionSettings) -> Observable.just(mockConnection))
Expand All @@ -169,7 +131,7 @@ public void setsTheSpecifiedUserAgentWhenSpecified() {
@Test
public void retainsTheUserAgentStringFromTheRequest() {
Connection mockConnection = mock(Connection.class);
when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(HttpResponse.response().build()));
when(mockConnection.write(any(HttpRequest.class))).thenReturn(Observable.just(response().build()));

SimpleHttpClient client = new SimpleHttpClient.Builder()
.setConnectionFactory((origin, connectionSettings) -> Observable.just(mockConnection))
Expand All @@ -194,4 +156,95 @@ public void requestWithNoHostOrUrlAuthorityCausesException() {

await(client.sendRequest(request));
}

@Test
public void sendsToDefaultHttpPort() {
Connection.Factory connectionFactory = mockConnectionFactory(mockConnection(response(OK).build()));

SimpleHttpClient client = new SimpleHttpClient.Builder()
.setConnectionFactory(connectionFactory)
.build();

client.sendRequest(get("/")
.header(HOST, "localhost")
.build());

ArgumentCaptor<Origin> originCaptor = ArgumentCaptor.forClass(Origin.class);
verify(connectionFactory).createConnection(originCaptor.capture(), any(Connection.Settings.class));

assertThat(originCaptor.getValue().host().getPort(), is(80));
}

@Test
public void sendsToDefaultHttpsPort() {
Connection.Factory connectionFactory = mockConnectionFactory(mockConnection(response(OK).build()));

SimpleHttpClient client = new SimpleHttpClient.Builder()
.setConnectionFactory(connectionFactory)
.build();

client.sendRequest(get("/")
.secure(true)
.header(HOST, "localhost")
.build());

ArgumentCaptor<Origin> originCaptor = ArgumentCaptor.forClass(Origin.class);
verify(connectionFactory).createConnection(originCaptor.capture(), any(Connection.Settings.class));

assertThat(originCaptor.getValue().host().getPort(), is(443));
}

private SimpleHttpClient httpClient() {
return new SimpleHttpClient.Builder()
.build();
}

private SimpleHttpClient httpsClient() {
return new SimpleHttpClient.Builder()
.connectionSettings(new ConnectionSettings(1000))
.tlsSettings(new TlsSettings.Builder()
.authenticate(false)
.build())
.responseTimeoutMillis(6000)
.build();
}

private FullHttpRequest httpRequest(int port) {
return get("http://localhost:" + port)
.header(HOST, "localhost:" + port)
.build();
}

private FullHttpRequest httpsRequest(int port) {
return get("https://localhost:" + port)
.header(HOST, "localhost:" + port)
.build();
}

private void withOrigin(Protocol protocol, IntConsumer portConsumer) {
WireMockServer server = new WireMockServer(wireMockConfig().dynamicPort().dynamicHttpsPort());

try {
server.start();
int port = protocol == HTTP ? server.port() : server.httpsPort();
server.stubFor(WireMock.get(urlStartingWith("/")).willReturn(aResponse().withStatus(200)));
portConsumer.accept(port);
} finally {
server.stop();
}
}

private Connection mockConnection(HttpResponse response) {
Connection connection = mock(Connection.class);
when(connection.write(any(HttpRequest.class))).thenReturn(Observable.just(response));
return connection;
}

private Connection.Factory mockConnectionFactory(Connection connection) {
Connection.Factory factory = mock(Connection.Factory.class);
when(factory.createConnection(any(Origin.class), any(Connection.Settings.class)))
.thenReturn(Observable.just(connection));
return factory;
}

}