I believe there is a timezone issue in the the core/src/main/java/feign/codec/ErrorDecoder.java when parsing the retry-after header in the "public Date apply(String retryAfter)" method.
The code in the mentioned class basically does:
public static void main(String[] args) throws ParseException {
final DateFormat RFC822_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
Date d = RFC822_FORMAT.parse(RETRY-HEADER);
}
I'm in the timezone Europe/Berlin, here a "Mon, 14 Aug 2023 13:32:06 GMT" retry-after header becomes a "Mon Aug 14 13:32:06 CEST 2023" Date object .
Unfortunately the RetryableException that is then thrown and handled by my customized Retryer just contains the Date object and not the raw response header, so I cannot fix it by parsing the retry-after header again.
I created a local workaround with a custom errordecoder (the convert functrion is the workaround itself, going through ZonedDateTime and invoking Instant):
public class CustomErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String methodKey, Response response) {
FeignException exception = feign.FeignException.errorStatus(methodKey, response);
String retryAfter = firstOrNull(response.headers(), RETRY_AFTER);
if (retryAfter != null) {
return new RetryableException(
response.status(),
exception.getMessage(),
response.request().httpMethod(),
exception,
convert(retryAfter),
response.request());
}
return exception;
}
private Date convert(String retryAfter) {
try {
ZonedDateTime zoned = ZonedDateTime.parse(retryAfter, DateTimeFormatter.RFC_1123_DATE_TIME);
return Date.from(zoned.toInstant());
} catch(Exception e) {
}
return null;
}
private <T> T firstOrNull(Map<String, Collection<T>> map, String key) {
if (map.containsKey(key) && !map.get(key).isEmpty()) {
return map.get(key).iterator().next();
}
return null;
}
}
I believe there is a timezone issue in the the core/src/main/java/feign/codec/ErrorDecoder.java when parsing the retry-after header in the "public Date apply(String retryAfter)" method.
The code in the mentioned class basically does:
I'm in the timezone Europe/Berlin, here a "Mon, 14 Aug 2023 13:32:06 GMT" retry-after header becomes a "Mon Aug 14 13:32:06 CEST 2023" Date object .
Unfortunately the RetryableException that is then thrown and handled by my customized Retryer just contains the Date object and not the raw response header, so I cannot fix it by parsing the retry-after header again.
I created a local workaround with a custom errordecoder (the convert functrion is the workaround itself, going through ZonedDateTime and invoking Instant):