假装客户端错误处理 - 抑制 Error/Exception 并转换为 200 成功响应

Feign Client Error Handling - Suppress the Error/Exception and convert to 200 success response

我正在使用假客户端连接到下游服务。

我得到一个要求,当下游服务端点之一 returns 400(它是部分成功的场景)时,我们的服务需要将其转换为 200 成功的响应值。

我正在寻找执行此操作的最佳方法。

我们正在使用错误解码器来处理错误,上述转换仅适用于一个端点而不适用于所有下游端点,并且注意到 decode() 方法应该 returns 返回异常。

您将需要创建自定义 Client 来尽早拦截 Response 以更改响应状态而不调用 ErrorDecoder。最简单的方法是在现有客户端上创建一个包装器并创建一个状态为 200 的新 Response。这是使用 Feign 的 ApacheHttpClient:

时的示例
public class ClientWrapper extends ApacheHttpClient {
   private ApacheHttpClient delegate;

   public ClientWrapper(ApacheHttpClient client) {
      this.client = client;
   }

   @Override
   public Response execute(Request request, Request.Options options) throws IOException {
      /* execute the request on the delegate */
      Response response = this.client.execute(request, options);

      /* check the response code and change */
      if (response.status() == 400) {
         response = Response.builder(response).status(200).build();
      }
      return response;
   }
}

这个定制的客户端可以用在任何你需要的 Feign 客户端上。

另一种方法是在错误解码器处抛出自定义异常,并在 spring 全局异常处理程序(使用 @RestControllerAdvice)

中将此自定义异常转换为成功
public class CustomErrorDecoder implements ErrorDecoder {

@Override
public Exception decode(String methodKey, Response response) {

    if (response.status() == 400 && response.request().url().contains("/wanttocovert400to200/clientendpoints") {
        ResponseData responseData;
        ObjectMapper mapper = new ObjectMapper();
        try {
            responseData = mapper.readValue(response.body().asInputStream(), ResponseData.class);
        } catch (Exception e) {
            responseData = new ResponseData();
        }
        return new PartialSuccessException(responseData); 
    }
    return FeignException.errorStatus(methodKey, response);
}}

异常处理程序如下

@RestControllerAdvice
public class GlobalControllerExceptionHandler {

    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(PartialSuccessException.class)
    public ResponseData handlePartialSuccessException(
            PartialSuccessException ex) {
        return ex.getResponseData();
    }
}