Apache Http客户端放置请求错误

时间:2014-04-15 13:34:52

标签: apache scala http

我尝试使用Apache Http客户端的PUT方法上传文件。代码如下;

  def putFile(resource: String, file: File): (Int, String) = {
    val httpClient = new DefaultHttpClient(connManager)
    httpClient.getCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(un, pw))
    val url = address + "/" + resource
    val put = new HttpPut(url)
    put.setEntity(new FileEntity(file, "application/xml"))

    executeHttp(httpClient, put) match {
      case Success(answer) => (answer.getStatusLine.getStatusCode, "Successfully uploaded file")
      case Failure(e) => {
        e.printStackTrace()
        (-1, e.getMessage)
      }
    }
  }

当我尝试运行该方法时,我会看到以下错误:

org.apache.http.NoHttpResponseException: The target server failed to respond
    at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:101)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:252)
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:281)
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:247)
    at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:219)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:298)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:633)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:454)
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)

我不知道出了什么问题?我能够做GET请求,但PUT似乎不起作用!关于我应该寻找的地方的任何线索?

2 个答案:

答案 0 :(得分:0)

查看服务器。如果GET有效,但PUT没有,那么你必须找出接收端。

此外,您可能希望编写一个简单的HTML文件,其中包含一个带有PUT方法的表单,以排除您的Java部件。

作为一个副节点:从技术上讲,它可能会阻止请求通过或响应到达你。最好设置一个虚拟HTTP服务器来进行测试。

也许它也是一个超时问题,所以服务器需要很长时间才能处理你的PUT。

答案 1 :(得分:0)

您尝试使用的连接是旧连接,因此请求失败。

但是为什么您只看到PUT请求的错误而没有看到GET请求的错误?

如果检查DefaultHttpRequestRetryHandler类,则将看到默认情况下HttpClient尝试自动从I / O异常中恢复。默认的自动恢复机制仅限于一些已知安全的例外。

  • HttpClient不会尝试从任何逻辑或HTTP协议错误(从HttpException类派生的错误)中恢复。
  • HttpClient将自动重试那些被认为是幂等的方法。 您的GET请求,而不是您的PUT请求!
  • 当HTTP请求仍被传输到目标服务器(即请求尚未完全传输到服务器)时,HttpClient将自动重试那些由于传输异常而失败的方法。

这就是为什么您没有注意到GET请求有任何错误的原因,因为重试机制可以处理它。

您应该定义一个CustomHttpRequestRetryHandler,以扩展DefaultHttpRequestRetryHandler。像这样:

public class CustomHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {

  @Override
  public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
    if(exception instanceof NoHttpResponseException) {
      return true;
    }
    return super.retryRequest(exception, executionCount, context);
  }

}

然后只需分配您的CustomHttpRequestRetryHandler

final HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setRetryHandler(new CustomHttpRequestRetryHandler());

就是这样,现在您的PUT请求由新的RetryHandler处理(就像GET默认是GET一样)