这与懒惰无关,而是与Response L.ByteString
Simple 模块和Response BodyReader
TLS 模块之间的区别有关。
你注意到 aBodyReader
是一个IO ByteString
. 但特别是它是一个可以重复的动作,每次都使用下一个字节块。它遵循的协议是它永远不会发送空字节字符串,除非它位于文件末尾。(BodyReader
可能被称为ChunkGetter
)。bip
下面就像你写的一样:从 中提取BodyReader
/IO ByteString
后Response
,它执行它以获取第一个块,并打印它。但是不要重复这个动作来获得更多——所以在这种情况下,我们只看到创世记的前几章。您需要的是一个循环来耗尽块,bop
如下所示,这会导致整个 King James Bible 溢出到控制台中。
{-# LANGUAGE OverloadedStrings #-}
import Network.HTTP.Client
import Network.HTTP.Client.TLS
import qualified Data.ByteString.Char8 as B
main = bip
-- main = bop
bip = do
manager <- newManager tlsManagerSettings
request <- parseRequest "https://raw.githubusercontent.com/michaelt/kjv/master/kjv.txt"
withResponse request manager $ \response -> do
putStrLn "The status code was: "
print (responseStatus response)
chunk <- responseBody response
B.putStrLn chunk
bop = do
manager <- newManager tlsManagerSettings
request <- parseRequest "https://raw.githubusercontent.com/michaelt/kjv/master/kjv.txt"
withResponse request manager $ \response -> do
putStrLn "The status code was: "
print (responseStatus response)
let loop = do
chunk <- responseBody response
if B.null chunk
then return ()
else B.putStr chunk >> loop
loop
循环不断返回以获取更多块,直到它得到一个代表 eof 的空字符串,因此在终端中它会打印到 Apocalypse 的末尾。
这种行为很简单,但有点技术性。您只能使用BodyReader
手写递归。但是http-client
图书馆的目的是使事情成为http-conduit
可能。那里的结果withResponse
有 type Response (ConduitM i ByteString m ())
。ConduitM i ByteString m ()
是字节流的管道类型;这个字节流将包含整个文件。
在http-client
/http-conduit
材料的原始形式中,Response
包含这样的导管;该BodyReader
部分后来被分解出来,http-client
因此它可以被不同的流媒体库(如pipes
.
所以举个简单的例子,在streaming
和streaming-bytestring
库对应的http材料中,withHTTP
给你一个类型的响应Response (ByteString IO ())
。 ByteString IO ()
顾名思义,是 IO 中出现的字节流的类型;ByteString Identity ()
将相当于一个惰性字节串(实际上是一个纯粹的块列表)。ByteString IO ()
在这种情况下,将代表整个字节流一直到天启。所以随着进口
import qualified Data.ByteString.Streaming.HTTP as Bytes -- streaming-utils
import qualified Data.ByteString.Streaming.Char8 as Bytes -- streaming-bytestring
该程序与惰性字节串程序相同:
bap = do
manager <- newManager tlsManagerSettings
request <- parseRequest "https://raw.githubusercontent.com/michaelt/kjv/master/kjv.txt"
Bytes.withHTTP request manager $ \response -> do
putStrLn "The status code was: "
print (responseStatus response)
Bytes.putStrLn $ responseBody response
实际上它稍微简单一些,因为你没有“从 IO 中提取字节”:
lazy_bytes <- responseStatus response
Lazy.putStrLn lazy_bytes
但只要写
Bytes.putStrLn $ responseBody response
您只需直接“打印”它们。如果你想从 KJV 的中间稍微查看一点,你可以用一个惰性字节串做你想做的事情,并以:
Bytes.putStrLn $ Bytes.take 1000 $ Bytes.drop 50000 $ responseBody response
然后你会看到一些关于亚伯拉罕的事情。
withHTTP
forstreaming-bytestring
只是隐藏了我们需要直接使用BodyReader
材料的递归循环http-client
。它与withHTTP
您在 中找到的 相同pipes-http
,它表示字节串块流为Producer ByteString IO ()
,与 相同http-conduit
。在所有这些情况下,一旦您掌握了字节流,您就可以使用流式 IO 框架的典型方式来处理它,而无需手写递归。他们都使用BodyReader
fromhttp-client
来做到这一点,这是图书馆的主要目的。