Skip to content

Commit

Permalink
Change ResponseInterceptor to use InvocationContext
Browse files Browse the repository at this point in the history
  • Loading branch information
velo committed Jun 21, 2022
1 parent ed5740e commit 072711b
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 33 deletions.
20 changes: 15 additions & 5 deletions core/src/main/java/feign/AsyncFeign.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,21 @@
*/
package feign;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.function.Supplier;
import feign.Logger.NoOpLogger;
import feign.Request.Options;
import feign.Target.HardCodedTarget;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.codec.ErrorDecoder;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

/**
* Enhances {@link Feign} to provide support for asynchronous clients. Context (for example for
Expand Down Expand Up @@ -106,6 +110,7 @@ public AsyncBuilder<C> decoder(Decoder decoder) {
* @see Builder#decode404()
* @deprecated
*/
@Deprecated
public AsyncBuilder<C> decode404() {
this.dismiss404 = true;
return this;
Expand Down Expand Up @@ -222,6 +227,11 @@ public AsyncBuilder<C> requestInterceptor(RequestInterceptor requestInterceptor)
return this;
}

public AsyncBuilder<C> responseInterceptor(ResponseInterceptor responseInterceptor) {
builder.responseInterceptor(responseInterceptor);
return this;
}

/**
* @see Builder#requestInterceptors(Iterable)
*/
Expand Down
15 changes: 10 additions & 5 deletions core/src/main/java/feign/Feign.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*/
package feign;

import static feign.ExceptionPropagationPolicy.NONE;
import feign.Logger.NoOpLogger;
import feign.ReflectiveFeign.ParseHandlersByName;
import feign.Request.Options;
Expand All @@ -27,7 +28,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import static feign.ExceptionPropagationPolicy.NONE;

/**
* Feign's purpose is to ease development against http apis that feign restfulness. <br>
Expand All @@ -51,7 +51,11 @@ public static Builder builder() {
*
* <pre>
* <ul>
* <li>{@code Route53}: would match a class {@code route53.Route53}</li>
* <li>{@code
* Route53
* }: would match a class {@code
* route53.Route53
* }</li>
* <li>{@code Route53#list()}: would match a method {@code route53.Route53#list()}</li>
* <li>{@code Route53#listAt(Marker)}: would match a method {@code
* route53.Route53#listAt(Marker)}</li>
Expand Down Expand Up @@ -97,8 +101,8 @@ public static String configKey(Method method) {
public static class Builder {

private final List<RequestInterceptor> requestInterceptors =
new ArrayList<RequestInterceptor>();
private ResponseInterceptor responseInterceptor = null;
new ArrayList<>();
private ResponseInterceptor responseInterceptor = ResponseInterceptor.DEFAULT;
private Logger.Level logLevel = Logger.Level.NONE;
private Contract contract = new Contract.Default();
private Client client = new Client.Default(null, null);
Expand Down Expand Up @@ -183,6 +187,7 @@ public Builder mapAndDecode(ResponseMapper mapper, Decoder decoder) {
* @since 8.12
* @deprecated
*/
@Deprecated
public Builder decode404() {
this.dismiss404 = true;
return this;
Expand Down Expand Up @@ -293,7 +298,7 @@ Builder forceDecoding() {
}

public <T> T target(Class<T> apiType, String url) {
return target(new HardCodedTarget<T>(apiType, url));
return target(new HardCodedTarget<>(apiType, url));
}

public <T> T target(Target<T> target) {
Expand Down
53 changes: 53 additions & 0 deletions core/src/main/java/feign/InvocationContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* 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 feign.codec.DecodeException;
import feign.codec.Decoder;
import java.io.IOException;

public class InvocationContext {

private final Decoder decoder;
private final MethodMetadata metadata;
private final Response response;

public InvocationContext(Decoder decoder, MethodMetadata metadata, Response response) {
this.decoder = decoder;
this.metadata = metadata;
this.response = response;
}

public Object proceed() {
try {
return decoder.decode(response, metadata.returnType());
} catch (IOException e) {
throw new DecodeException(response.status(), "decode error cause of io exception",
response.request(), e);
}
}

public Decoder getDecoder() {
return decoder;
}

public MethodMetadata getMetadata() {
return metadata;
}

public Response getResponse() {
return response;
}

}
13 changes: 7 additions & 6 deletions core/src/main/java/feign/ResponseInterceptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@
*/
public interface ResponseInterceptor {

ResponseInterceptor DEFAULT = InvocationContext::proceed;

/**
* Called for response around decode, user can use supplied {@link Function} decoder function to
* decode response data.
* Called for response around decode, must either manually invoke
* {@link InvocationContext#proceed} or manually create a new response object
*
* @param response
* @param decoder
* @return
* @param invocationContext information surrounding the response been decoded
* @return decoded response
*/
void aroundDecode(Response response, Function<Response, Object> decoder);
Object aroundDecode(InvocationContext invocationContext);

}
22 changes: 5 additions & 17 deletions core/src/main/java/feign/SynchronousMethodHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,16 @@
import static feign.ExceptionPropagationPolicy.UNWRAP;
import static feign.FeignException.errorExecuting;
import static feign.Util.checkNotNull;
import feign.InvocationHandlerFactory.MethodHandler;
import feign.Request.Options;
import feign.codec.Decoder;
import feign.codec.ErrorDecoder;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import feign.InvocationHandlerFactory.MethodHandler;
import feign.Request.Options;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.codec.ErrorDecoder;

final class SynchronousMethodHandler implements MethodHandler {

Expand Down Expand Up @@ -134,18 +133,7 @@ Object executeAndDecode(RequestTemplate template, Options options) throws Throwa
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);

if (decoder != null) {
if (responseInterceptor != null) {
responseInterceptor.aroundDecode(response, (res) -> {
try {
return decoder.decode(res, metadata.returnType());
} catch (IOException e) {
throw new DecodeException(res.status(), "decode error cause of io exception",
res.request(), e);
}
});
} else {
return decoder.decode(response, metadata.returnType());
}
return responseInterceptor.aroundDecode(new InvocationContext(decoder, metadata, response));
}

CompletableFuture<Object> resultFuture = new CompletableFuture<>();
Expand Down

0 comments on commit 072711b

Please sign in to comment.