在 apache httpclient 中通过拦截器刷新访问令牌

Refresh Access Token via Interceptor in apache httpclient

使用拦截器,我尝试更新访问令牌。但是代码不起作用...如何使用 http 客户端拦截器更新访问令牌?

try (CloseableHttpClient httpClient = HttpClients.custom().
            addExecInterceptorAfter(ChainElement.PROTOCOL.name(), "a1", (request, scope, chain) -> {
                ClassicHttpResponse response = chain.proceed(request, scope);
                if (response.getCode() == HttpStatus.SC_UNAUTHORIZED) {
                    userAuthBean.updateAccessTokenFromAPI();
                    request.addHeader("Authorization", "Bearer " + userAuthBean.getAccessToken());
                    chain.proceed(request, scope);
                }
                return response;
            })
            .build())
    {
        HttpGet request = new HttpGet(uri);
        request.addHeader("Authorization", "Bearer " + userAuthBean.getAccessToken());
        try (CloseableHttpResponse response = httpClient.execute(request)) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity, StandardCharsets.UTF_8);
                System.out.println(result);
            }
        } catch (IOException | ParseException ioException) {
            ioException.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return result;

此代码用于在获得 403 的情况下重试请求,理想情况下不应在拦截器中。拦截器通常要直接编写,它会操纵 current* request/response 并导致调用链进行处理。它们使您的代码变得丑陋,并使调试变得更加简单,因为在大多数情况下,逻辑是隐藏的。

一般来说,这些拦截器最好用于记录请求(至 ELK/Kafka 或任何地方)并为 *every 添加缺失的 attributes/headers(如果有的话)请求通过 http 客户端(即使这是 IMO 代码气味)。

相反,您需要链接 Function,如下所示,

  public static void main(String[] args) throws IOException {
    getWithAuthTokenRetry.apply(new Request.Builder().url("http://google.com").build());
  }

  public static Function<Request, Response> get =
      (req) -> {
        OkHttpClient okHttpClient = new OkHttpClient();
        Response res = null;
        try {
          res = okHttpClient.newCall(req).execute(); // Simulate calls!!
        } catch (IOException e) {
          e.printStackTrace();
        }
        return res;
      };

  public static Function<Request, Response> getWithAuthTokenRetry =
      request -> {
        Function<Response, Response> authenticateAndRetryFunction =
            res -> {
              if (res != null && res.code() == 200) { //403 Here
                String authToken = "Generated AuthToken"; // Simulating new AuthToken
                Request updatedRequest = request.newBuilder().header("Auth", authToken).build();
                System.out.println(updatedRequest.headers());
                res = get.apply(updatedRequest);
              }
              return res;
            };
        return get.andThen(authenticateAndRetryFunction).apply(request);
      };

这是一个非常广泛的实现,没有正确处理异常,但我想这些可以根据要求计算出来。

此外,不需要为每个请求都创建 ClosableHttpClient,使用 ClosableHttpClient 创建一个 HttpComponentsClientHttpRequestFactory 实例。