Skip to content

Commit

Permalink
JDK 11 HttpClient async implement for AsyncFeign. (#1330)
Browse files Browse the repository at this point in the history
* java11 async http client for AsyncFeign

* java 11 httpclient not allow some header

* add unit test

* add license

* remove unused annotation

* Merge branch 'master' of https://github.com/OpenFeign/feign into asyncfeign-java11-impl

� Conflicts:
�	java11/src/main/java/feign/http2client/Http2Client.java

* port connectionTimeout feature of Http2Client to AsyncHttpClient

* fix format

* Combined Sync and Async clients into a single class

Co-authored-by: UzimakiNaruto <[email protected]>
Co-authored-by: Kevin Davis <[email protected]>
Co-authored-by: Marvin Froeder <[email protected]>
Co-authored-by: Marvin Froeder <[email protected]>
  • Loading branch information
5 people authored Oct 17, 2021
1 parent f991e05 commit f0e5fd4
Show file tree
Hide file tree
Showing 4 changed files with 1,149 additions and 20 deletions.
5 changes: 5 additions & 0 deletions java11/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@
<type>jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
Expand Down
74 changes: 54 additions & 20 deletions java11/src/main/java/feign/http2client/Http2Client.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2012-2020 The Feign Authors
* Copyright 2012-2021 The Feign Authors
*
* 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
Expand All @@ -13,11 +13,6 @@
*/
package feign.http2client;

import feign.Client;
import feign.Request;
import feign.Request.Options;
import feign.Response;
import feign.Util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
Expand All @@ -32,11 +27,28 @@
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers;
import java.time.Duration;
import java.util.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalLong;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;
import java.util.stream.Collectors;
import feign.AsyncClient;
import feign.Client;
import feign.Request;
import feign.Request.Options;
import feign.Response;
import feign.Util;

public class Http2Client implements Client {
public class Http2Client implements Client, AsyncClient<Object> {

private final HttpClient client;

Expand All @@ -59,9 +71,16 @@ public Http2Client(HttpClient client) {

@Override
public Response execute(Request request, Options options) throws IOException {
final HttpRequest httpRequest = newRequestBuilder(request, options).build();
HttpClient clientForRequest = getOrCreateClient(options);
final HttpRequest httpRequest;
try {
httpRequest = newRequestBuilder(request, options)
.version(client.version())
.build();
} catch (URISyntaxException e) {
throw new IOException("Invalid uri " + request.url(), e);
}

HttpClient clientForRequest = getOrCreateClient(options);
HttpResponse<byte[]> httpResponse;
try {
httpResponse = clientForRequest.send(httpRequest, BodyHandlers.ofByteArray());
Expand All @@ -70,17 +89,37 @@ public Response execute(Request request, Options options) throws IOException {
throw new IOException("Invalid uri " + request.url(), e);
}

return toFeignResponse(request, httpResponse);
}

@Override
public CompletableFuture<Response> execute(Request request,
Options options,
Optional<Object> requestContext) {
HttpRequest httpRequest;
try {
httpRequest = newRequestBuilder(request, options).build();
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Invalid uri " + request.url(), e);
}

HttpClient clientForRequest = getOrCreateClient(options);
CompletableFuture<HttpResponse<byte[]>> future =
clientForRequest.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
return future.thenApply(httpResponse -> toFeignResponse(request, httpResponse));
}

protected Response toFeignResponse(Request request, HttpResponse<byte[]> httpResponse) {
final OptionalLong length = httpResponse.headers().firstValueAsLong("Content-Length");

final Response response = Response.builder()
return Response.builder()
.body(new ByteArrayInputStream(httpResponse.body()),
length.isPresent() ? (int) length.getAsLong() : null)
.reason(httpResponse.headers().firstValue("Reason-Phrase").orElse("OK"))
.request(request)
.status(httpResponse.statusCode())
.headers(castMapCollectType(httpResponse.headers().map()))
.build();
return response;
}

private HttpClient getOrCreateClient(Options options) {
Expand Down Expand Up @@ -116,13 +155,8 @@ private static java.net.http.HttpClient.Builder newClientBuilder(Options options
.connectTimeout(Duration.ofMillis(options.connectTimeoutMillis()));
}

private Builder newRequestBuilder(Request request, Options options) throws IOException {
URI uri;
try {
uri = new URI(request.url());
} catch (final URISyntaxException e) {
throw new IOException("Invalid uri " + request.url(), e);
}
private Builder newRequestBuilder(Request request, Options options) throws URISyntaxException {
URI uri = new URI(request.url());

final BodyPublisher body;
final byte[] data = request.body();
Expand All @@ -135,7 +169,7 @@ private Builder newRequestBuilder(Request request, Options options) throws IOExc
final Builder requestBuilder = HttpRequest.newBuilder()
.uri(uri)
.timeout(Duration.ofMillis(options.readTimeoutMillis()))
.version(Version.HTTP_2);
.version(client.version());

final Map<String, Collection<String>> headers = filterRestrictedHeaders(request.headers());
if (!headers.isEmpty()) {
Expand Down
25 changes: 25 additions & 0 deletions java11/src/test/java/feign/http2client/test/CustomPojo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Copyright 2012-2020 The Feign Authors
*
* 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 feign.http2client.test;

public class CustomPojo {

private final String name;
private final Integer number;

CustomPojo(String name, Integer number) {
this.name = name;
this.number = number;
}
}
Loading

0 comments on commit f0e5fd4

Please sign in to comment.