Http-Conduit经常连接失败

10

我正在编写一个应用程序,它将通过HTTP下载一些文件。在某个阶段之前,我使用以下代码片段来下载页面主体:

import network.HTTP
simpleHTTP (getRequest "http://www.haskell.org/") >>= getResponseBody

它之前运行良好,但无法使用HTTPS协议建立连接。因此,为了解决这个问题,我已经切换到HTTP-Conduit并使用以下代码:

simpleHttp' :: Manager -> String -> IO (C.Response LBS.ByteString)
simpleHttp' manager url = do
     request <- parseUrl url
     runResourceT $ httpLbs request manager

它可以连接到HTTPS,但是出现了一个新的令人沮丧的问题。大约每五次连接会失败,并出现异常:

getpics.hs: FailedConnectionException "i.imgur.com" 80

我相信这是HTTP-Conduit的问题,因为在同样的页面集合上(不包括https页面),network.HTTP运行良好。

有人遇到过这样的问题并知道解决方案或更好的(且简单,因为这是一项简单的任务,应该不需要超过几行代码)替代Conduit库吗?


我也遇到了同样的问题!我之前以为是我连接的终端(stripe和postmark)出了问题,直到看到这篇文章。感谢你提出这个问题。 - Luke Hoersten
1
一些注释- 1. haskell.org 在本周末宕机,因此您展示的第一个代码片段将无法工作,2.启动Wireshark并查看发生了什么... 您可以观察整个http连接,对于https,详细信息将丢失,但至少您可以看到tcp头是否通过,3.您提到了https,但您展示的错误显示端口80,这是用于http的。无论如何,我尝试了该代码,并为我工作,可以连续多次获取http://google.com和https://google.com。 - jamshidh
我有一些页面集,其中有 http 和 https 页面,因此端口号为 80。如果我使用一个链接运行程序,它永远不会失败。但当我尝试在单个执行中获取几个链接时,它会失败。 - Trismegistos
你正在运行哪个版本的http-conduit?另外,我想再强调一下,一个好的Wireshark日志记录问题发生的情况会告诉我很多信息。你知道如何运行Wireshark吗? - jamshidh
1个回答

2
一种简单的替代方案是使用curl包。它支持HTTP、HTTPS和许多其他替代协议,以及许多选项来定制其行为。代价是引入一个外部依赖libcurl,需要构建该包。
示例:
import Network.Curl

main :: IO ()
main = do
  let addr = "https://google.com/" 
  -- Explicit type annotation is required for calls to curlGetresponse_.
  -- Use ByteString instead of String for higher performance:
  r <- curlGetResponse_ addr [] :: IO (CurlResponse_ [(String,String)] String)

  print $ respHeaders r
  putStr $ respBody r

更新:我尝试复制您的问题,但对我来说一切都正常。您能否发布一个简短、自包含、可编译的示例,以演示问题?我的代码:
import Control.Monad
import qualified Data.Conduit as C
import qualified Data.ByteString.Lazy as LBS
import Network.HTTP.Conduit

simpleHttp'' :: String -> Manager -> C.ResourceT IO (Response LBS.ByteString)
simpleHttp'' url manager = do
     request <- parseUrl url
     httpLbs request manager

main :: IO ()
main = do
  let url = "http://i.imgur.com/"
      count = 100
  rs <- withManager $ \m -> replicateM count (simpleHttp'' url m)
  mapM_ (print . responseStatus) $ rs

我认为这个解决方案是针对Unix的。 - Trismegistos
@Trismegistos 你需要一个非Unix平台吗?是哪一个?还是你需要你的应用程序在不同平台上可移植?Libcurl可以在许多平台上工作,包括Windows和MacOS,因此也许可以使其工作。 - Petr
我需要Unix和Windows,但实际上我一直在将它与Python进行比较,看到urllib的无痛工作方式,这让我感到沮丧。Haskell社区将其工具宣传为某种神创造,但却无法应对获取HTTP / HTTPS页面的平凡问题。 - Trismegistos
1
@Trismegistos 我已经多次使用http-conduit 2.0.0.3测试了上述代码片段,没有出现任何故障。要么是您的网络设置有问题,要么是您正在以不同的方式使用http-conduit,这容易导致错误。请发布一个完整的代码示例来演示问题,这可能是我们能找到解决方法的唯一途径。 - Petr
1
@Trismegistos 我试过了,没有任何问题。你试过在另一台电脑上运行它吗?也许这是某种只在特定条件下显现的错误。 - Petr
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接