我正在使用最新的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.ProtocolExec.execute(ProtocolExec.java:185) 在 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) ...还有6个
我发现了以下错误报告:https://github.com/http-builder-ng/http-builder-ng/issues/10,但是它已分配给另一个问题。
是什么导致错误?如何在Apache httpclient中使用基本身份验证?我不知道什么是“可重复HTTP请求”,据我所知,所有客户端需要设置的都是Authorization标头。我是否可能在服务器上配置了某些错误,从而需要“可重复的” HTTP请求?
答案 0 :(得分:0)
似乎基本的身份验证模型在apache httpclient中被破坏了。该库尝试绕过身份验证并发送不带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);
}
});
}
答案 1 :(得分:0)
我不同意OP自己的解决方案,因为它某种程度上非常骇人,并且绕过了图书馆的凭证机制。
HTTP实体有几种实体类型,如here所述。因此,既然您知道了,就无法在方案中使用可重复的实体,如何使用独立的实体或使用缓冲区的包装器。
您可以使用单线实现。没有尝试过,我认为正确的解决方案是:
grammar RecordGrammar;
records : record+ EOF;
record : Record name tracks EndRecord;
tracks : track+;
track : Track length EndTrack;
length : Length Number;
name : Name+;
Record : 'record';
EndRecord : 'endrecord';
Track : 'track';
EndTrack : 'endtrack';
Length : 'length';
Name : [a-zA-Z]+;
Number : [0-9]+;
WS : [ \t\r\n]+ -> skip;