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 <ff578505546@qq.com>
Co-authored-by: Kevin Davis <kdavisk6@gmail.com>
Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
Co-authored-by: Marvin Froeder <marvin.froeder@dovetailstudios.com>
  • Loading branch information
5 people authored Oct 17, 2021
1 parent 98786bb commit 2c7f407
Show file tree
Hide file tree
Showing 4 changed files with 1,200 additions and 24 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
78 changes: 54 additions & 24 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
*
* <p>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,6 +13,7 @@
*/
package feign.http2client;

import feign.AsyncClient;
import feign.Client;
import feign.Request;
import feign.Request.Options;
Expand All @@ -32,11 +33,22 @@
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;

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

private final HttpClient client;

Expand All @@ -54,9 +66,14 @@ 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 @@ -65,19 +82,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()
.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;
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();
}

private HttpClient getOrCreateClient(Options options) {
Expand Down Expand Up @@ -114,13 +149,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 @@ -134,7 +164,7 @@ private Builder newRequestBuilder(Request request, Options options) throws IOExc
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
*
* <p>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
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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 2c7f407

Please sign in to comment.