来自 Network.HTTP.simpleHTTP 的 ErrorClosed 异常 - 尝试使用 haxr 通过 XML-RPC 上传图像

Posted

技术标签:

【中文标题】来自 Network.HTTP.simpleHTTP 的 ErrorClosed 异常 - 尝试使用 haxr 通过 XML-RPC 上传图像【英文标题】:ErrorClosed exception from Network.HTTP.simpleHTTP -- trying to upload images via XML-RPC with haxr 【发布时间】:2012-07-01 22:18:47 【问题描述】:

我正在尝试使用 haxr 3000.8.5 将图像上传到使用 metaWeblog API 的 WordPress 博客——具体来说,是 newMediaObject 方法。

我已经让它适用于 small 图像,成功上传了 PNG 和 JPG 格式的 20x20 图标。但是,当我尝试中等大小的图像(比如 300x300)时,我得到了一个 ErrorClosed 异常,大概来自 HTTP 包(我做了一些源代码潜水,发现 haxr 最终调用 Network.HTTP.simpleHTTP)。

谁能解释为什么调用simpleHTTP 可能会因ErrorClosed 而失败?也欢迎提出尝试和潜在解决方法的建议。

这里是full tcpdump output from a successful upload 和from an unsuccessful upload 的链接。

下面还显示了(经过清理的)代码,以备不时之需。

import           Network.XmlRpc.Client      (remote)
import           Network.XmlRpc.Internals   (Value(..), toValue)
import           Data.Char                  (toLower)
import           System.FilePath            (takeFileName, takeExtension)
import qualified Data.ByteString.Char8 as B
import           Data.Functor               ((<$>))

uploadMediaObject :: FilePath -> IO Value
uploadMediaObject file = do
  media <- mkMediaObject file
  remote "http://someblog.wordpress.com/xmlrpc.php" "metaWeblog.newMediaObject"
    "default" "username" "password" media

-- Create the required struct representing the image.
mkMediaObject :: FilePath -> IO Value
mkMediaObject filePath = do
  bits <- B.unpack <$> B.readFile filePath
  return $ ValueStruct
    [ ("name", toValue fileName)
    , ("type", toValue fileType)
    , ("bits", ValueBase64 bits)
    ]
  where
    fileName = takeFileName filePath
    fileType = case (map toLower . drop 1 . takeExtension) fileName of
                 "png"  -> "image/png"
                 "jpg"  -> "image/jpeg"
                 "jpeg" -> "image/jpeg"
                 "gif"  -> "image/gif"

main = do
  v <- uploadMediaObject "images/puppy.png"
  print v

【问题讨论】:

您是否尝试过使用 tcpdump 或 wireshark 来检查 HTTP 会话? 感谢您的建议。我真的对网络知之甚少,尤其是在调试方面。我在问题中添加了一些 tcpdump 输出。 @BrentYorgey:我认为您会希望将该输出编辑到您的问题中。即使它设法适合您在评论中获得的有限空间,在此处阅读格式正确也容易得多。 是的,抱歉,按 Enter 太快了。 默认输出没有足够的有用信息。我建议安装 Wireshark 或使用“tcpdump -s 0 -X”来获取完整的数据包。 【参考方案1】:
21:59:56.813021 IP 192.168.1.148.39571 > ..http: Flags [.]
22:00:01.922598 IP ..http > 192.168.1.148.39571: Flags [F.]

由于客户端没有发送任何数据,服务器在 3-4 秒超时后关闭连接,以防止慢速和类似的 ddos​​ 攻击。 (F为FIN标志,关闭一个方向的双向连接)。

服务器不等待客户端关闭连接(等待 eof/0 == recv(fd))而是使用 close() 系统调用;如果服务器上的内核接收到更多数据,它将以 [R]eset 数据包进行响应,正如您在转储末尾看到的那样。

我猜是客户端先打开http连接,然后准备数据,时间太长了。

【讨论】:

谢谢,这正是我需要知道的!事实证明,Haskell 的懒惰对我造成了很大的影响。修复很重要(需要修补 haxr),但我现在已经让它工作了。

以上是关于来自 Network.HTTP.simpleHTTP 的 ErrorClosed 异常 - 尝试使用 haxr 通过 XML-RPC 上传图像的主要内容,如果未能解决你的问题,请参考以下文章

为啥 WCF 服务能够处理来自不同进程的调用而不是来自线程的调用

来自 viewDidAppear 的 Segue 调用有效,但不是来自 viewWillAppear

求职作业帮 C++方向面经

来自 CWnd 的 ReleaseDC 覆盖来自 winuser 的 ReleaseDC

来自麦克风的声音与来自扬声器的声音

Liferay,来自搜索的 Freemarker 错误模板,但不是来自其他链接