Skip to content

Commit

Permalink
HTTP 1 parser, CONNECT host:port fix, HTTP2 support tests
Browse files Browse the repository at this point in the history
Signed-off-by: Jorge Bescos Gascon <jorge.bescos.gascon@oracle.com>
  • Loading branch information
jbescos committed Aug 8, 2023
1 parent d4636ac commit 13a9592
Show file tree
Hide file tree
Showing 10 changed files with 618 additions and 139 deletions.
4 changes: 4 additions & 0 deletions nima/tests/integration/webclient/webclient/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
<groupId>io.helidon.nima.webclient</groupId>
<artifactId>helidon-nima-webclient</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.nima.http2</groupId>
<artifactId>helidon-nima-http2-webclient</artifactId>
</dependency>
<dependency>
<groupId>io.helidon.nima.webserver</groupId>
<artifactId>helidon-nima-webserver</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates.
*
* 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 io.helidon.nima.tests.integration.webclient;

import static io.helidon.common.http.Http.Method.GET;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.fail;

import io.helidon.common.http.Http;
import io.helidon.nima.http2.webclient.Http2Client;
import io.helidon.nima.testing.junit5.webserver.ServerTest;
import io.helidon.nima.testing.junit5.webserver.SetUpRoute;
import io.helidon.nima.webclient.api.HttpClient;
import io.helidon.nima.webclient.api.HttpClientResponse;
import io.helidon.nima.webclient.api.Proxy;
import io.helidon.nima.webclient.api.Proxy.ProxyType;
import io.helidon.nima.webclient.http1.Http1Client;
import io.helidon.nima.webserver.WebServer;
import io.helidon.nima.webserver.http.HttpRouting;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

@ServerTest
class AuthHttpProxyTest {

private static final String PROXY_HOST = "localhost";
private static final String USER = "user";
private static final String PASSWORD = "password";
private int proxyPort;
private HttpProxy httpProxy;

private final HttpClient<?> clientHttp1;
private final HttpClient<?> clientHttp2;

AuthHttpProxyTest(WebServer server) {
String uri = "http://localhost:" + server.port();
this.clientHttp1 = Http1Client.builder().baseUri(uri).build();
this.clientHttp2 = Http2Client.builder().baseUri(uri).build();
}

@SetUpRoute
static void routing(HttpRouting.Builder router) {
router.route(GET, "/get", Routes::get);
}

@BeforeEach
void before() {
httpProxy = new HttpProxy(0, USER, PASSWORD);
httpProxy.start();
proxyPort = httpProxy.connectedPort();
assertThat(httpProxy.counter(), is(0));
}

@AfterEach
void after() {
httpProxy.stop();
}

@Test
void testUserPasswordCorrect1() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password(PASSWORD.toCharArray()).port(proxyPort).build();
successVerify(proxy, clientHttp1);
}

@Test
void testUserPasswordCorrect2() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password(PASSWORD.toCharArray()).port(proxyPort).build();
successVerify(proxy, clientHttp2);
}

@Test
void testUserPasswordNotCorrect1() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password("wrong".toCharArray()).port(proxyPort).build();
failVerify(proxy, clientHttp1);
}

@Test
void testUserPasswordNotCorrect2() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password("wrong".toCharArray()).port(proxyPort).build();
failVerify(proxy, clientHttp2);
}

private void successVerify(Proxy proxy, HttpClient<?> client) {
try (HttpClientResponse response = client.get("/get").proxy(proxy).request()) {
assertThat(response.status(), is(Http.Status.OK_200));
String entity = response.entity().as(String.class);
assertThat(entity, is("Hello"));
}
assertThat(httpProxy.counter(), is(1));
}

private void failVerify(Proxy proxy, HttpClient<?> client) {
try (HttpClientResponse response = client.get("/get").proxy(proxy).request()) {
fail("Expected exception");
} catch (IllegalStateException e) {
assertThat(e.getMessage(), is("Proxy sent wrong HTTP response code: 401 Unauthorized"));
}
assertThat(httpProxy.counter(), is(1));
}

private static class Routes {
private static String get() {
return "Hello";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright (c) 2023 Oracle and/or its affiliates.
*
* 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 io.helidon.nima.tests.integration.webclient;

import static io.helidon.common.http.Http.Method.GET;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.fail;

import io.helidon.common.configurable.Resource;
import io.helidon.common.http.Http;
import io.helidon.common.pki.Keys;
import io.helidon.nima.common.tls.Tls;
import io.helidon.nima.http2.webclient.Http2Client;
import io.helidon.nima.testing.junit5.webserver.ServerTest;
import io.helidon.nima.testing.junit5.webserver.SetUpRoute;
import io.helidon.nima.testing.junit5.webserver.SetUpServer;
import io.helidon.nima.webclient.api.HttpClient;
import io.helidon.nima.webclient.api.HttpClientResponse;
import io.helidon.nima.webclient.api.Proxy;
import io.helidon.nima.webclient.api.Proxy.ProxyType;
import io.helidon.nima.webclient.http1.Http1Client;
import io.helidon.nima.webserver.WebServer;
import io.helidon.nima.webserver.WebServerConfig.Builder;
import io.helidon.nima.webserver.http.HttpRouting;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

@ServerTest
class AuthHttpsProxyTest {

private static final String PROXY_HOST = "localhost";
private static final String USER = "user";
private static final String PASSWORD = "password";
private int proxyPort;
private HttpProxy httpProxy;

private final HttpClient<?> clientHttp1;
private final HttpClient<?> clientHttp2;

@SetUpRoute
static void routing(HttpRouting.Builder router) {
router.route(GET, "/get", Routes::get);
}

@SetUpServer
static void server(Builder builder) {
Keys privateKeyConfig = Keys.builder()
.keystore(keystore -> keystore
.keystore(Resource.create("server.p12"))
.passphrase("password"))
.build();

Tls tls = Tls.builder()
.privateKey(privateKeyConfig.privateKey().get())
.privateKeyCertChain(privateKeyConfig.certChain())
.trustAll(true)
.endpointIdentificationAlgorithm(Tls.ENDPOINT_IDENTIFICATION_NONE)
.build();

builder.tls(tls);
}

@BeforeEach
void before() {
httpProxy = new HttpProxy(0, USER, PASSWORD);
httpProxy.start();
proxyPort = httpProxy.connectedPort();
assertThat(httpProxy.counter(), is(0));
}

@AfterEach
void after() {
httpProxy.stop();
}

AuthHttpsProxyTest(WebServer server) {
int port = server.port();

Tls tls = Tls.builder()
.trustAll(true)
.endpointIdentificationAlgorithm(Tls.ENDPOINT_IDENTIFICATION_NONE)
.build();

this.clientHttp1 = Http1Client.builder().baseUri("https://localhost:" + port).tls(tls).build();
this.clientHttp2 = Http2Client.builder().baseUri("https://localhost:" + port).tls(tls).build();
}

@Test
void testUserPasswordCorrect1() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password(PASSWORD.toCharArray()).port(proxyPort).build();
successVerify(proxy, clientHttp1);
}

@Test
void testUserPasswordCorrect2() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password(PASSWORD.toCharArray()).port(proxyPort).build();
successVerify(proxy, clientHttp2);
}

@Test
void testUserPasswordNotCorrect1() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password("wrong".toCharArray()).port(proxyPort).build();
failVerify(proxy, clientHttp1);
}

@Test
void testUserPasswordNotCorrect2() {
Proxy proxy = Proxy.builder().type(ProxyType.HTTP).host(PROXY_HOST)
.username(USER).password("wrong".toCharArray()).port(proxyPort).build();
failVerify(proxy, clientHttp2);
}

private void failVerify(Proxy proxy, HttpClient<?> client) {
try (HttpClientResponse response = client.get("/get").proxy(proxy).request()) {
fail("Expected exception");
} catch (IllegalStateException e) {
assertThat(e.getMessage(), is("Proxy sent wrong HTTP response code: 401 Unauthorized"));
}
assertThat(httpProxy.counter(), is(1));
}

private void successVerify(Proxy proxy, HttpClient<?> client) {
try (HttpClientResponse response = client.get("/get").proxy(proxy).request()) {
assertThat(response.status(), is(Http.Status.OK_200));
String entity = response.entity().as(String.class);
assertThat(entity, is("Hello"));
}
}

private static class Routes {
private static String get() {
return "Hello";
}
}
}

0 comments on commit 13a9592

Please sign in to comment.