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

Add relativeUris configuration to determine if relative or absolute URI will be used in the request #6952

Merged
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
5 changes: 5 additions & 0 deletions nima/webclient/webclient/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<artifactId>junit-jupiter-params</artifactId>
<groupId>org.junit.jupiter</groupId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-all</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@ public Http1ClientBuilder useSystemServiceLoader(boolean useServiceLoader) {
configBuilder.servicesUseServiceLoader(useServiceLoader);
return this;
}

/**
* Can be set to {@code true} to force the use of relative URIs in all requests,
* regardless of the presence or absence of proxies or no-proxy lists.
*
* @param relativeUris relative URIs flag
* @return updated builder instance
*/
public Http1ClientBuilder relativeUris(boolean relativeUris) {
configBuilder.relativeUris(relativeUris);
return this;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ interface Http1ClientConfig extends ClientConfig {
@ConfiguredOption("true")
boolean servicesUseServiceLoader();

// TODO Set the default value to false when proxy is implemented and see Http1CallChainBase.prologue for other changes
@ConfiguredOption("true")
Comment on lines +68 to +69
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please create follow up issue/s for these TODOs you are having in this PR.

boolean relativeUris();

@Singular
List<WebClientService> services();
}
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,13 @@ abstract WebClientServiceResponse doProceed(ClientConnection connection,
BufferData writeBuffer);

void prologue(BufferData nonEntityData, WebClientServiceRequest request, UriHelper uri) {
// TODO When proxy is implemented, change default value of Http1ClientConfig.relativeUris to false
// and below conditional statement to:
// proxy == Proxy.noProxy() || proxy.noProxyPredicate().apply(finalUri) || clientConfig.relativeUris
String schemeHostPort = clientConfig.relativeUris() ? "" : uri.scheme() + "://" + uri.host() + ":" + uri.port();
nonEntityData.writeAscii(request.method().text()
+ " "
+ schemeHostPort
+ uri.pathWithQueryAndFragment(request.query(), request.fragment())
+ " HTTP/1.1\r\n");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
import java.io.OutputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.StringTokenizer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Stream;

import io.helidon.common.GenericType;
import io.helidon.common.buffers.BufferData;
Expand All @@ -39,13 +41,18 @@
import io.helidon.nima.webclient.WebClient;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import static io.helidon.common.testing.http.junit5.HttpHeaderMatcher.hasHeader;
import static io.helidon.common.testing.http.junit5.HttpHeaderMatcher.noHeader;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.params.provider.Arguments.arguments;

class ClientRequestImplTest {
private static final Http.HeaderValue REQ_CHUNKED_HEADER = Http.Header.createCached(
Expand Down Expand Up @@ -193,6 +200,28 @@ void testSkipUrlEncoding() {
assertThat(uri.getRawFragment(), is("someFragment,"));
}

@ParameterizedTest
@MethodSource("relativeUris")
void testRelativeUris(boolean relativeUris, boolean outputStream, String requestUri, String expectedUriStart) {
Http1Client client = WebClient.builder().relativeUris(relativeUris).build();
FakeHttp1ClientConnection connection = new FakeHttp1ClientConnection();
Http1ClientRequest request = client.put(requestUri);
request.connection(connection);
Http1ClientResponse response;
if (outputStream) {
response = getHttp1ClientResponseFromOutputStream(request, new String[] {"Sending Something"});
} else {
response = request.submit("Sending Something");
}

assertThat(response.status(), is(Http.Status.OK_200));
StringTokenizer st = new StringTokenizer(connection.getPrologue(), " ");
// skip method part
st.nextToken();
// Validate URI part
assertThat(st.nextToken(), startsWith(expectedUriStart));
}

private static void validateSuccessfulResponse(Http1Client client, ClientConnection connection) {
String requestEntity = "Sending Something";
Http1ClientRequest request = client.put("http://localhost:" + dummyPort + "/test");
Expand Down Expand Up @@ -248,13 +277,36 @@ private static Http1ClientResponse getHttp1ClientResponseFromOutputStream(Http1C
return response;
}

private static Stream<Arguments> relativeUris() {
return Stream.of(
// OutputStream (chunk request)
arguments(false, true, "http://www.dummy.com/test", "http://www.dummy.com:80/"),
arguments(false, true, "http://www.dummy.com:1111/test", "http://www.dummy.com:1111/"),
arguments(false, true, "https://www.dummy.com/test", "https://www.dummy.com:443/"),
arguments(false, true, "https://www.dummy.com:1111/test", "https://www.dummy.com:1111/"),
arguments(true, true, "http://www.dummy.com/test", "/test"),
arguments(true, true, "http://www.dummy.com:1111/test", "/test"),
arguments(true, true, "https://www.dummy.com/test", "/test"),
arguments(true, true, "https://www.dummy.com:1111/test", "/test"),
// non-OutputStream (single entity request)
arguments(false, false, "http://www.dummy.com/test", "http://www.dummy.com:80/"),
arguments(false, false, "http://www.dummy.com:1111/test", "http://www.dummy.com:1111/"),
arguments(false, false, "https://www.dummy.com/test", "https://www.dummy.com:443/"),
arguments(false, false, "https://www.dummy.com:1111/test", "https://www.dummy.com:1111/"),
arguments(true, false, "http://www.dummy.com/test", "/test"),
arguments(true, false, "http://www.dummy.com:1111/test", "/test"),
arguments(true, false, "https://www.dummy.com/test", "/test"),
arguments(true, false, "https://www.dummy.com:1111/test", "/test"));
}

private static class FakeHttp1ClientConnection implements ClientConnection {
private final DataReader clientReader;
private final DataWriter clientWriter;
private final DataReader serverReader;
private final DataWriter serverWriter;
private Throwable serverException;
private ExecutorService webServerEmulator;
private String prologue;

FakeHttp1ClientConnection() {
ArrayBlockingQueue<byte[]> serverToClient = new ArrayBlockingQueue<>(1024);
Expand Down Expand Up @@ -290,6 +342,11 @@ public String channelId() {
return null;
}

// This will be used for testing the element of Prologue
String getPrologue() {
return prologue;
}

private DataWriter writer(ArrayBlockingQueue<byte[]> queue) {
return new DataWriter() {
@Override
Expand Down Expand Up @@ -361,8 +418,8 @@ private void webServerHandle() {
// Read prologue
int lineLength = serverReader.findNewLine(16384);
if (lineLength > 0) {
//String prologue = serverReader.readAsciiString(lineLength);
serverReader.skip(lineLength + 2); // skip Prologue + CRLF
prologue = serverReader.readAsciiString(lineLength);
serverReader.skip(2); // skip CRLF
}

// Read Headers
Expand Down