feign
feign copied to clipboard
Support Response Interceptors
In my project, I use the request interceptor to sign the request. I thought that there would be a corresponding response interceptor to verify the signature, but I didn't find it. Is there a better way?
Short answer is cause nobody implemented it.
As workaround, you could use a customized decoded to validate your response and then delegate decoding to whatever decoder you need.
I also could use a response interceptor: my use case is to capture some response headers and run some logic on them, possibly only if the response is successful (e.g. only when the status is 200 and the decoding throws no exceptions).
What would be the appropriate place to do such change, design-wise?
Maybe in SynchronousMethodHandler.executeAndDecode(...)
, right after the decoder runs the method decoder.decode(response, metadata.returnType());
?
(I am not considering the asyncResponseHandler
because it's marked as @Experimental
)
@Experimental
is just for the sake of informing API may change in a unpredictable way and break compatibility between minor releases.
Just to give us a little extra flexibility =)
So, RequestInterceptor
happens right after encoder and before client is invoked...
ResponseInterceptor
then would happen after client, before decoder. So yes, SynchronousMethodHandler.executeAndDecode
seems to be the right place, just not after decoder, but before.
Now, what are you trying to do that you can't do by chain decoders?
class MyResponseValidatorDecoder implements Decoder {
private final Decoder realDecoder; //populated by constructor
// inside decode method
{
if(response.getStatus() == 302) return new RedirectObject(response);
return realDecoder.decode();
}
}
//usage
FeignBuilder.decoder(new MyResponseValidatorDecoder(new JacksonDecoder()));
How can i send another request when response in some status, and then retry request.
The steps like this.
request: biz -> reponse: access_token expire -> request: refresh access_token ->request: retry biz
I've updated the title of this issue to better reflect the ask and added the proposal label. If this receives enough support we will consider this enhancement.
This would be a great feature if we can get it.
I too have a use case where I can leverage ResponseInterceptor functionality. Will be good to see this implemented, instead of performing a workaround.
I too have a need for this kind of functionality even though my work around is working as well. The response interceptor just would need to happen before decoder. In this case all data is moved around in encrypted string so it is needed to be decrypted before say GsonDecoder can access and decode the json.
My current decryption decoder is like so if someone finds it useful:
`public class GsonDecryptionDecoder extends GsonDecoder {
@Override
public Object decode(Response response, Type type) throws IOException, FeignException {
try (Reader reader = response.body().asReader(Charset.defaultCharset())) {
String encryptedMessage = CharStreams.toString(reader);
String decryptedBody = decryptJsonResp(encryptedMessage);
Response decryptedResponse = Response.builder()
.body(decryptedBody, Charset.defaultCharset())
.headers(response.headers())
.reason(response.reason())
.status(response.status())
.request(response.request())
.build();
return super.decode(decryptedResponse, type);
} catch (Exception e) {
throw new DecodeException(response.status(), "Failed to decode response", response.request(), e);
}
}
}`
I also need ResponseInterceptor, especially because decoder workaround is not usable for me - the decoder is not called for methods returning void. I need to validate response headers and ignore the response if it does not contain certain header.
Hi @kdavisk6 , I also need ResponseInterceptor. Could you please consider enhancing it?
I need to catch a header datum in Response to validate it. The following solution is working, but It is ugly. Instead of this I want to write ResponseInterceptor to catch the header rate-limit datum.
At the moment, I appreciate any workaround helps.
Response response = myService.callMethod(request);
// for catching header data
Integer rateLimit = Integer.valueOf(response.headers().get("x-rate-limit-remaining").stream().findFirst().orElse("0"));
// For getting body
Decoder.Default decoder = new Decoder.Default();
CustomResponse customResponse;
try {
String body = (String) decoder.decode(response, String.class);
ObjectMapper mapper = new ObjectMapper();
customResponse = mapper.readValue(body, CustomResponse.class);
} catch (Exception e) {
log.error("Error occured during realty transfer response decoding. Error: {}", e.getMessage());
return;
}
Huge thnx
We are open to evaluating any proposals for this.
Feel free to open a PR and tag me to review.
Would be good to also be able to throw custom exceptions from decoder or response interceptor, currently all exceptions get wrapped in DecodeException.