Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
velo committed Jun 21, 2022
2 parents 21d31be + daed53a commit ed5740e
Show file tree
Hide file tree
Showing 16 changed files with 1,284 additions and 38 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Version 11.9

* `OkHttpClient` now implements `AsyncClient`

### Version 10.9

* Configurable to disable streaming mode for Default client by verils (#1182)
Expand Down
5 changes: 2 additions & 3 deletions benchmark/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@
<name>Feign Benchmark (JMH)</name>

<properties>
<jmh.version>1.34</jmh.version>
<jmh.version>1.35</jmh.version>
<rx.netty.version>0.5.3</rx.netty.version>
<rx.java.version>1.3.8</rx.java.version>
<netty.version>4.1.74.Final</netty.version>

<netty.version>4.1.77.Final</netty.version>
<main.basedir>${project.basedir}/..</main.basedir>
</properties>

Expand Down
3 changes: 2 additions & 1 deletion core/src/main/java/feign/Contract.java
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method me

if (parameterTypes[i] == URI.class) {
data.urlIndex(i);
} else if (!isHttpAnnotation && parameterTypes[i] != Request.Options.class) {
} else if (!isHttpAnnotation
&& !Request.Options.class.isAssignableFrom(parameterTypes[i])) {
if (data.isAlreadyProcessed(i)) {
checkState(data.formParams().isEmpty() || data.bodyIndex() == null,
"Body parameters cannot be used with form parameters.%s", data.warnings());
Expand Down
11 changes: 6 additions & 5 deletions core/src/main/java/feign/MethodInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,15 @@ class MethodInfo {
MethodInfo(Class<?> targetType, Method method) {
this.configKey = Feign.configKey(targetType, method);

final Type type = method.getGenericReturnType();
final Type type = Types.resolve(targetType, targetType, method.getGenericReturnType());

if (method.getReturnType() != CompletableFuture.class) {
this.asyncReturnType = false;
this.underlyingReturnType = type;
} else {
if (type instanceof ParameterizedType
&& Types.getRawType(type).isAssignableFrom(CompletableFuture.class)) {
this.asyncReturnType = true;
this.underlyingReturnType = ((ParameterizedType) type).getActualTypeArguments()[0];
} else {
this.asyncReturnType = false;
this.underlyingReturnType = type;
}
}

Expand Down
106 changes: 106 additions & 0 deletions core/src/test/java/feign/MethodInfoTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright 2012-2022 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;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;

@RunWith(Enclosed.class)
public class MethodInfoTest {

public static class AsyncClientTest {
public interface AsyncClient {
CompletableFuture<String> log();
}

@Test
public void testCompletableFutureOfString() throws Exception {
MethodInfo mi = new MethodInfo(AsyncClient.class, AsyncClient.class.getMethod("log"));
assertEquals("AsyncClient#log()", mi.configKey());
assertTrue(mi.isAsyncReturnType());
assertEquals(String.class, mi.underlyingReturnType());
}
}

public static class GenericAsyncClientTest {
public interface GenericAsyncClient<T> {
T log();
}

public interface AsyncClient extends GenericAsyncClient<CompletableFuture<String>> {
}

@Test
public void testGenericCompletableFutureOfString() throws Exception {
MethodInfo mi = new MethodInfo(AsyncClient.class, AsyncClient.class.getMethod("log"));
assertEquals("AsyncClient#log()", mi.configKey());
assertTrue(mi.isAsyncReturnType());
assertEquals(String.class, mi.underlyingReturnType());
}
}

public static class SyncClientTest {
public interface SyncClient {
String log();
}

@Test
public void testString() throws Exception {
MethodInfo mi = new MethodInfo(SyncClient.class, SyncClient.class.getMethod("log"));
assertEquals("SyncClient#log()", mi.configKey());
assertFalse(mi.isAsyncReturnType());
assertEquals(String.class, mi.underlyingReturnType());
}
}

public static class GenericSyncClientTest {
public interface GenericSyncClient<T> {
T log();
}

public interface SyncClient extends GenericSyncClient<List<String>> {
}

public static class ListOfStrings implements ParameterizedType {
@Override
public Type[] getActualTypeArguments() {
return new Type[] {String.class};
}

@Override
public Type getRawType() {
return List.class;
}

@Override
public Type getOwnerType() {
return null;
}
}

@Test
public void testListOfStrings() throws Exception {
MethodInfo mi = new MethodInfo(SyncClient.class, SyncClient.class.getMethod("log"));
assertEquals("SyncClient#log()", mi.configKey());
assertFalse(mi.isAsyncReturnType());
assertTrue(Types.equals(new ListOfStrings(), mi.underlyingReturnType()));
}
}
}
21 changes: 21 additions & 0 deletions core/src/test/java/feign/OptionsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,19 @@
@SuppressWarnings("deprecation")
public class OptionsTest {

static class ChildOptions extends Request.Options {
public ChildOptions(int connectTimeoutMillis, int readTimeoutMillis) {
super(connectTimeoutMillis, readTimeoutMillis);
}
}

interface OptionsInterface {
@RequestLine("GET /")
String get(Request.Options options);

@RequestLine("POST /")
String getChildOptions(ChildOptions options);

@RequestLine("GET /")
String get();
}
Expand Down Expand Up @@ -66,4 +75,16 @@ public void normalResponseTest() {

assertThat(api.get(new Request.Options(1000, 4 * 1000))).isEqualTo("foo");
}

@Test
public void normalResponseForChildOptionsTest() {
final MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("foo").setBodyDelay(3, TimeUnit.SECONDS));

final OptionsInterface api = Feign.builder()
.options(new ChildOptions(1000, 1000))
.target(OptionsInterface.class, server.url("/").toString());

assertThat(api.getChildOptions(new ChildOptions(1000, 4 * 1000))).isEqualTo("foo");
}
}
48 changes: 33 additions & 15 deletions hc5/src/main/java/feign/hc5/ApacheHttp5Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,40 @@

import static feign.Util.UTF_8;
import static feign.Util.enumForName;
import feign.Client;
import feign.Request;
import feign.Response;
import feign.Util;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.config.Configurable;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.*;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.io.entity.ByteArrayEntity;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.io.support.ClassicRequestBuilder;
import org.apache.hc.core5.net.URIBuilder;
import org.apache.hc.core5.net.URLEncodedUtils;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.*;
import feign.*;

/**
* This module directs Feign's http requests to Apache's
Expand Down Expand Up @@ -97,8 +113,7 @@ ClassicHttpRequest toClassicHttpRequest(Request request, Request.Options options
requestBuilder.setUri(uri.getScheme() + "://" + uri.getAuthority() + uri.getRawPath());

// request query params
final List<NameValuePair> queryParams =
URLEncodedUtils.parse(uri, requestBuilder.getCharset());
final List<NameValuePair> queryParams = URLEncodedUtils.parse(uri, requestBuilder.getCharset());
for (final NameValuePair queryParam : queryParams) {
requestBuilder.addParameter(queryParam);
}
Expand Down Expand Up @@ -174,22 +189,22 @@ Response toFeignResponse(ClassicHttpResponse httpResponse, Request request) thro

final String reason = httpResponse.getReasonPhrase();

final Map<String, Collection<String>> headers = new HashMap<String, Collection<String>>();
final Map<String, Collection<String>> headers = new HashMap<>();
for (final Header header : httpResponse.getHeaders()) {
final String name = header.getName();
final String value = header.getValue();

Collection<String> headerValues = headers.get(name);
if (headerValues == null) {
headerValues = new ArrayList<String>();
headerValues = new ArrayList<>();
headers.put(name, headerValues);
}
headerValues.add(value);
}

return Response.builder()
.protocolVersion(enumForName(Request.ProtocolVersion.class,
httpResponse.getVersion().format()))
.protocolVersion(
enumForName(Request.ProtocolVersion.class, httpResponse.getVersion().format()))
.status(statusCode)
.reason(reason)
.headers(headers)
Expand Down Expand Up @@ -222,7 +237,6 @@ public InputStream asInputStream() throws IOException {
return entity.getContent();
}

@SuppressWarnings("deprecation")
@Override
public Reader asReader() throws IOException {
return new InputStreamReader(asInputStream(), UTF_8);
Expand All @@ -236,7 +250,11 @@ public Reader asReader(Charset charset) throws IOException {

@Override
public void close() throws IOException {
EntityUtils.consume(entity);
try {
EntityUtils.consume(entity);
} finally {
httpResponse.close();
}
}
};
}
Expand Down
3 changes: 1 addition & 2 deletions hc5/src/main/java/feign/hc5/AsyncApacheHttp5Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,7 @@ Response toFeignResponse(SimpleHttpResponse httpResponse, Request request) {
.reason(reason)
.headers(headers)
.request(request)
.body(httpResponse
.getBodyBytes())
.body(httpResponse.getBodyBytes())
.build();
}

Expand Down
10 changes: 7 additions & 3 deletions httpclient/src/main/java/feign/httpclient/ApacheHttpClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.Configurable;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.entity.ByteArrayEntity;
Expand Down Expand Up @@ -233,6 +231,12 @@ public Reader asReader(Charset charset) throws IOException {
@Override
public void close() throws IOException {
EntityUtils.consume(entity);
try {
EntityUtils.consume(entity);
} finally {
if (httpResponse instanceof CloseableHttpResponse)
((CloseableHttpResponse) httpResponse).close();
}
}
};
}
Expand Down
8 changes: 7 additions & 1 deletion okhttp/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2012-2021 The Feign Authors
Copyright 2012-2022 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 Down Expand Up @@ -54,5 +54,11 @@
<artifactId>mockwebserver</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Loading

0 comments on commit ed5740e

Please sign in to comment.