在 FeignClient 中处理 HTTP 重定向

Handling HTTP redirections in FeignClient

FeignClient 是一个非常漂亮的工具,但不幸的是,如果你需要做一些与 Spring 众神的意图稍有不同的事情,你就会受到伤害。

当前情况:我使用外部第三方 REST 服务,嗯,关于 REST 的概念有趣。特别是,如果您向他们发送正确的 JSON,他们会在正文中 return HTTP 302 和 JSON。

不用说,FeignClient 真的非常不喜欢这种恶作剧。我的界面:

@FeignClient(value = "someClient", configuration = SomeClientDecoderConfiguration.class)
public interface SomeClient {
    @RequestMapping(method = RequestMethod.POST, path = "${someClient.path}",
    produces = MediaType.APPLICATION_JSON_VALUE)
    JsonOrderCreateResponse orderCreate(JsonOrderCreateRequest request, @RequestHeader("Authorization") String authHeader);
}

我已经有了自定义配置和错误解码器,但这些仅适用于 HTTP 4xx 和 5xx。如果系统遇到302,结果是这样的:

http://pastebin.com/raw/cGKWc4yg

我如何防止这种情况发生并强制 FeignClient 像处理 200 一样处理 302?

虽然没有办法强制 FeignClient 在没有疯狂的解决方法的情况下正常处理超过 2xx 的任何内容,但有办法以最小的麻烦来处理它。请注意,您将需要 非常新的 版本!我必须在 POM 中输入:

<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-core</artifactId>
    <version>1.5.9</version>
</dependency>

那么,怎么做呢?

在伪造客户端实现中,您需要 return 响应的任何方法。就是这样。

如果您 return 响应,框架将以特殊方式运行 - 如果状态超过 2xx,它不会抛出任何异常,也不会像某些人那样尝试重试多次...有天赋的.. . child。换句话说,没有恶作剧。耶!

示例:

import feign.Response;

@RequestMapping(method = RequestMethod.POST, path = "${someClient.path}")
Response doThisOrThat(JsonSomeRequest someJson, @RequestHeader("Authorization") String authHeader);

当然,您需要手动实际处理响应(前面提到的最小麻烦):

private JsonSomeResponse resolveResponse(JsonSomeRequest jsonRequest, String accessToken)
{
    Response response = someClient.doThisOrThat(jsonRequest, "Bearer " + accessToken);
    JsonSomeResponse jsonResponse = null;
    String resultBody = "";
    try {
        try (BufferedReader buffer = new BufferedReader(new InputStreamReader(response.body().asInputStream()))) {
            resultBody = buffer.lines().collect(Collectors.joining("\n"));
        }
        jsonResponse = objectMapper.readValue(resultBody, JsonSomeResponse.class);
    } catch (IOException ex) {
        throw new RuntimeException("Failed to process response body.", ex);
    }
    // just an example of using exception
    if (response.status() >= 400) thrown new OmgWeAllAreDeadException();
    return jsonResponse;
}

然后你可以做任何你想做的事,检查 response.status() 以抛出你自己的异常,以与 200 相同的方式处理任何状态代码(如 302)的响应(哦,恐怖!)等等。