代码之家  ›  专栏  ›  技术社区  ›  9ilsdx 9rvj 0lo

添加基本身份验证后出现不可重复的请求异常

  •  0
  • 9ilsdx 9rvj 0lo  · 技术社区  · 7 年前

    我正在使用最新的apache http:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient-osgi</artifactId>
        <version>4.5.6</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpcore-osgi</artifactId>
        <version>4.4.10</version>
    </dependency>
    

    我做了以下手术:

    public void store(InputStream input) throws IOException {
        HttpClientBuilder builder = HttpClientBuilder.create();
        if (StringUtils.isNotBlank(username)) {
          CredentialsProvider provider = new BasicCredentialsProvider();
          UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username.trim(), StringUtils.trimToEmpty(password));
          provider.setCredentials(AuthScope.ANY, credentials);
          builder.setDefaultCredentialsProvider(provider);
        }
        HttpClient client = builder.build();
        HttpPost post  = new HttpPost(uri);
        post.setEntity(new InputStreamEntity(input));
        HttpResponse response = client.execute(post);
    }   
    

    原因:org.apache.http.client.NonRepeatableRequestException: 无法使用不可重复的请求实体重试请求。在 org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:226) 在 在 org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111) 在 org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)

    我发现了以下错误报告: https://github.com/http-builder-ng/http-builder-ng/issues/10 ,但是它被分配给另一个问题。

    2 回复  |  直到 7 年前
        1
  •  0
  •   9ilsdx 9rvj 0lo    7 年前

    ApacheHttpClient中的基本身份验证模型似乎已损坏。库试图绕过身份验证并在没有 Authorization 头,当然失败了。然后库尝试重新发送请求,当然失败了,因为 InputStream 不能倒带。

    BasicCredentialsProvider 使用 HttpRequestInterceptor 设置标题:

    HttpClientBuilder builder = HttpClientBuilder.create();
    if (StringUtils.isNotBlank(username)) {
      builder.addInterceptorFirst(new HttpRequestInterceptor()
      {
    
        @Override
        public void process(HttpRequest request, HttpContext context) throws HttpException, IOException
        {
          String token = Base64.getEncoder().encodeToString((username + ":" + password).getBytes(StandardCharsets.UTF_8));
          request.addHeader("Authorization", "Basic "+token);
        }
      });
    }   
    
        2
  •  0
  •   UniversE    7 年前

    我不同意OP自己的解决方案,因为它在某种程度上非常老套,并且绕过了库的凭证机制。

    here . 现在您知道了,您不能在场景中使用可重复的实体,不如使用自包含的实体或使用缓冲区的包装器。

    你只需要一行代码就可以做到这一点。我认为正确的解决办法是,在没有尝试过的情况下:

    post.setEntity(new BufferedHttpEntity(new InputStreamEntity(input)));