【问题标题】:Apache HttpClient 4.x behaving strange when uploading larger files?上传较大文件时 Apache HttpClient 4.x 表现奇怪?
【发布时间】:2023-03-22 09:33:01
【问题描述】:

我正在使用 java(和 scala)开发和测试一个简单的客户端-服务器应用程序。

服务器基于com.sun.net.httpserver.HttpServer,允许通过基本的RESTful 接口使用POST 和PUT 操作上传文件。上传操作使用我们自己实现的Digest authentication进行限制,在浏览器、curl和Apache HttpClient中经过测试和工作。

上传客户端包装Apache HttpClient 4.1.2并通过http执行PUT操作以上传文件实体。文件的内容类型在标头中指定为application/xml,一次只上传一个文件。

在上传不同大小的文件时,可能会观察到一种奇怪的行为:

  • 上传大小小于或等于 1.076.006 字节的文件 成功
  • 大小大于或等于 1.122.158 字节的文件 失败java.net.SocketException: Broken pipe

确切的临界大小未知,因为我手动创建了不同大小的文件以接近最大工作大小

管道损坏的原因是,客户端以某种方式忽略了 www-authenticate-response 上传该大小的文件,正如服务器日志所记录的那样。 “忽略”意味着它只发送多 (4) 条根本不包含身份验证标头的消息。 但是较小的文件运行良好,并且客户端在www-authenticate-response 之后立即正确地发送具有正确质询-响应的身份验证请求。

上传可以在 curl 中处理各种大小的文件,所以没有问题。

因此,此时,您可以说:“您的客户端中存在一些错误。”好的,我希望如此,但是我也尝试了一个开源 java RESTclient(也包装了 apache httpclient),它的行为完全相同

我们在互联网上使用此客户端进行了尝试,它也与描述的相同。所以现在,我只是希望我错过了在Apache HttpClient 中设置一些重要的东西,这会导致这种错误行为,而开源 RESTclient 的开发人员也错过了它......任何想法都会很棒!

【问题讨论】:

    标签: java apache file-upload httpclient digest-authentication


    【解决方案1】:

    很可能是多种因素共同导致了这种情况

    (1) 在发送带有不包含身份验证标头的请求的大型请求实体时,您的客户端很可能不使用“expect-continue”握手。

    (2) 服务器提前检测到请求未达到预期,而不是读取和丢弃完整的请求正文,而是提前以 401 状态响应并在其结束时关闭连接。在我看来,这是服务器方面的 HTTP 协议违规。

    (3) 虽然一些 HTTP 代理可以处理早期响应,但由于 Java 阻塞 I/O 的限制,Apache HttpClient 不能(执行线程可以从阻塞套接字读取或写入,但不能同时读取)。

    有多种方法可以解决这个问题,“expect-continue”握手是最简单、最自然的一种。或者,可以在执行大型 POST 或 PUT 请求之前执行简单的 HEAD 或 GET 请求以强制进行 HTTP 身份验证。 HttpClient 能够为同一逻辑 HTTP 会话中的后续请求重新使用身份验证数据。

    【讨论】:

    • 感谢您的解释,这完全有道理!现在我选择“期望继续”解决方案。在客户端它只是翻转一个布尔值。服务器上的握手现在正在进行中,我非常相信这应该可以解决问题。
    • 奇怪的是,底层的 sun httpserver 总是 以 100-continue 响应,而不涉及应用程序!在我看来,它违反了协议(参见 RFC 2616“使用 100(继续)状态”,httpserver-source:docjar.com/html/api/sun/net/httpserver/ServerImpl.java.html)。但是我已经实现了您的第二个解决方案,在发送大量数据之前通过第二个请求触发身份验证。这行得通,非常感谢!
    • @mtsz 这不关我的事,但现在有这么多像样的可嵌入 HTTP 服务器,你为什么还要使用 Sun 的 ServerImpl?
    • 因为我在大学做一个项目,而这就是我的教授选择和嵌入的……我注意到几乎没有人在使用它。但是我学到了一些有趣的东西,所以总的来说还不错;)至少我会更加欣赏体面的服务器!
    猜你喜欢
    • 2011-04-02
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 2015-04-06
    • 2015-10-17
    • 1970-01-01
    • 2018-04-21
    • 2013-12-14
    相关资源
    最近更新 更多