Hello.
I'm creating a bean with an ErrorDecoder to implement a custom retry policy. I also have a Retryer bean.
My error decoder:
@Bean
public ErrorDecoder errorDecoder(OAuth2ClientContext oAuth2ClientContext) {
Default errorDecoder = new Default();
return (methodKey, response) -> {
FeignException exception = FeignException.errorStatus(methodKey, response);
if (<custom-check>) {
return new RetryableException(
response.status(),
response.reason(),
response.request().httpMethod(),
exception,
null,
response.request());
}
return errorDecoder.decode(methodKey, response);
};
}
My retryer:
@Bean("customFeignRetrier")
public Retryer retryer() {
return new Retryer.Default(this.period, this.maxPeriod, this.retriesLimit);
}
Making a simple integration test to check the custom policy, when I force the first request to fail, the second throws this exception:
Caused by: java.lang.IllegalArgumentException: url values must be not be absolute.
at feign.RequestTemplate.uri(RequestTemplate.java:434)
at feign.RequestTemplate.uri(RequestTemplate.java:421)
at mypackage.UrlEncodingInterceptor.apply(UrlEncodingInterceptor.java:14)
at feign.SynchronousMethodHandler.targetRequest(SynchronousMethodHandler.java:161)
at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:110)
at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:89)
My feign client used in the test case:
@FeignClient(contextId = "Check", name = "check", url = "http://localhost:${server.port}")
public interface ClientCredentialsFeignClient {
@GetMapping("/check")
ResponseEntity<SecurityData> check();
}
My test case:
void test() {
this.wireMockServer.stubFor(
WireMock.get(WireMock.urlEqualTo("/check"))
.willReturn(WireMock.aResponse().withStatus(401)));
Assertions.assertThrows(FeignException.class, () -> this.client.check());
// verify a mock I have to check if the request was retried
}
Debugging the test execution, the exception is thrown because of another custom interceptor my team are using:
/** Interceptor to fix url encoding of issue: https://github.com/OpenFeign/feign/issues/1190 */
public class UrlEncodingInterceptor implements RequestInterceptor {
@SneakyThrows
@Override
public void apply(RequestTemplate template) {
template.uri(URLDecoder.decode(template.path(), "UTF-8"));
}
}
In the first request the template.path() appears to be only the path (/check in this case)..
In the second request it is also returning the full URL of the request (http://localhost:1234/check in this case).
Why template.path() returns different values for each execution? Any workaround on this?
Versions:
spring-cloud-starter-openfeign - 3.1.1 (tried to update to 3.1.3 but same error)
feign-core - 11.8
spring-boot - 2.6.6
spring-cloud - 2021.0.1
Comment From: OlgaMaciaszek
Hello @lucasoares, please provide a minimal, complete, verifiable example that reproduces the issue. Preferably as a small GH project with an executable class/ tests that reproduce the issue, not as code snippets that require additional setup on our part.
Comment From: spring-cloud-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-cloud-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Comment From: YuryKorovko
@lucasoares Hi, did you solve that issue ?
Comment From: lucasoares
@lucasoares Hi, did you solve that issue ?
Well, not exactly..
I added the following check in the UrlEncodingInterceptor my team was using:
/** Interceptor to fix url encoding of issue: https://github.com/OpenFeign/feign/issues/1190 */
public class UrlEncodingInterceptor implements RequestInterceptor {
@SneakyThrows
@Override
public void apply(RequestTemplate template) {
// this if
if (template.path().startsWith("http") || !template.path().startsWith("/")) {
return;
}
template.uri(URLDecoder.decode(template.path(), StandardCharsets.UTF_8));
}
}
So it will not break in the second execution.