Skip to content

Commit

Permalink
Support for lastEndpointUri() in Webclient responses (#7113)
Browse files Browse the repository at this point in the history
* Support for lastEndpointUri() in Webclient responses. This method can be used to obtain the final redirect URI of the corresponding request. Tests updated.

* Lazy conversion to URI.
  • Loading branch information
spericas authored Jun 27, 2023
1 parent 8479515 commit 067ee8f
Show file tree
Hide file tree
Showing 7 changed files with 43 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ UriHelper uriHelper() {
private Http2ClientResponse readResponse(Http2ClientStream stream) {
Http2Headers headers = stream.readHeaders();

return new ClientResponseImpl(headers, stream);
return new ClientResponseImpl(headers, stream, uri);
}

private byte[] entityBytes(Object entity) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022 Oracle and/or its affiliates.
* Copyright (c) 2022, 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.
Expand All @@ -16,21 +16,26 @@

package io.helidon.nima.http2.webclient;

import java.net.URI;

import io.helidon.common.http.ClientResponseHeaders;
import io.helidon.common.http.Headers;
import io.helidon.common.http.Http;
import io.helidon.nima.http.media.ReadableEntity;
import io.helidon.nima.http2.Http2Headers;
import io.helidon.nima.webclient.UriHelper;

class ClientResponseImpl implements Http2ClientResponse {
private final Http.Status responseStatus;
private final ClientResponseHeaders responseHeaders;
private final UriHelper lastEndpointUri;
private Http2ClientStream stream;

ClientResponseImpl(Http2Headers headers, Http2ClientStream stream) {
ClientResponseImpl(Http2Headers headers, Http2ClientStream stream, UriHelper lastEndpointUri) {
this.responseStatus = headers.status();
this.responseHeaders = ClientResponseHeaders.create(headers.httpHeaders());
this.stream = stream;
this.lastEndpointUri = lastEndpointUri;
}

@Override
Expand All @@ -48,6 +53,11 @@ public ReadableEntity entity() {
return stream.entity().copy(() -> this.stream = null);
}

@Override
public URI lastEndpointUri() {
return lastEndpointUri.toUri();
}

@Override
public void close() {
if (stream != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ void testRedirect() {
try (Http1ClientResponse response = injectedHttp1client.put("/redirect")
.submit("Test entity")) {
assertThat(response.status(), is(Http.Status.OK_200));
assertThat(response.lastEndpointUri().getPath(), is("/afterRedirect"));
assertThat(response.as(String.class), is(EXPECTED_GET_AFTER_REDIRECT_STRING));
}
}
Expand All @@ -314,6 +315,7 @@ void testRedirectKeepMethod() {

try (Http1ClientResponse response = injectedHttp1client.put("/redirectKeepMethod")
.submit("Test entity")) {
assertThat(response.lastEndpointUri().getPath(), is("/afterRedirect"));
assertThat(response.status(), is(Http.Status.NO_CONTENT_204));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.helidon.nima.webclient;

import java.io.InputStream;
import java.net.URI;

import io.helidon.common.GenericType;
import io.helidon.common.http.Headers;
Expand Down Expand Up @@ -84,6 +85,13 @@ default <T extends Source<?>> void source(GenericType<T> sourceType, T source) {
throw new UnsupportedOperationException("No source available for " + sourceType);
}

/**
* URI of the last request. (after redirection)
*
* @return last URI
*/
URI lastEndpointUri();

/**
* Closes the response.
* This may have no impact on the underlying connection.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ public String toString() {
return scheme + "://" + authority + (path.startsWith("/") ? "" : "/") + path;
}

/**
* Convert instance to {@link java.net.URI}.
*
* @return the converted URI
*/
public URI toUri() {
return URI.create(toString());
}

/**
* Scheme of this URI.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ private ClientResponseImpl invokeServices(WebClientService.Chain callChain,
serviceResponse.reader(),
mediaContext,
clientConfig.mediaTypeParserMode(),
uri,
complete);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package io.helidon.nima.webclient.http1;

import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.ServiceLoader;
Expand All @@ -42,6 +43,7 @@
import io.helidon.nima.http.media.ReadableEntityBase;
import io.helidon.nima.webclient.ClientConnection;
import io.helidon.nima.webclient.ClientResponseEntity;
import io.helidon.nima.webclient.UriHelper;
import io.helidon.nima.webclient.http.spi.Source;
import io.helidon.nima.webclient.http.spi.SourceHandlerProvider;

Expand Down Expand Up @@ -70,6 +72,7 @@ class ClientResponseImpl implements Http1ClientResponse {
private final List<String> trailerNames;
// Media type parsing mode configured on client.
private final ParserMode parserMode;
private final UriHelper lastEndpointUri;

private ClientConnection connection;
private long entityLength;
Expand All @@ -83,6 +86,7 @@ class ClientResponseImpl implements Http1ClientResponse {
DataReader reader,
MediaContext mediaContext,
ParserMode parserMode,
UriHelper lastEndpointUri,
CompletableFuture<Void> whenComplete) {
this.responseStatus = responseStatus;
this.requestHeaders = requestHeaders;
Expand All @@ -92,6 +96,7 @@ class ClientResponseImpl implements Http1ClientResponse {
this.mediaContext = mediaContext;
this.parserMode = parserMode;
this.channelId = connection.channelId();
this.lastEndpointUri = lastEndpointUri;
this.whenComplete = whenComplete;

if (responseHeaders.contains(Header.CONTENT_LENGTH)) {
Expand Down Expand Up @@ -214,6 +219,11 @@ private ReadableEntity entity(ClientRequestHeaders requestHeaders,
return ReadableEntityBase.empty();
}

@Override
public URI lastEndpointUri() {
return lastEndpointUri.toUri();
}

private BufferData readEntityChunked(int estimate) {
int endOfChunkSize = reader.findNewLine(256);
if (endOfChunkSize == 256) {
Expand Down

0 comments on commit 067ee8f

Please sign in to comment.