2

http-clientチュートリアルを使用して、TLS 接続を使用して応答本文を取得しています。printによって呼び出されていることを確認できるので、次のフラグメントの出力への応答全体を強制withResponseしないのはなぜですか?print

withResponse request manager $ \response -> do
    putStrLn $ "The status code was: " ++
    body <- (responseBody response)
    print body

代わりにこれを書く必要があります:

response <- httpLbs request manager

putStrLn $ "The status code was: " ++
           show (statusCode $ responseStatus response)
print $ responseBody response

印刷したい本文は怠惰なByteStringです。print値全体を出力する必要があるかどうかはまだわかりません。

instance Show ByteString where
    showsPrec p ps r = showsPrec p (unpackChars ps) r
4

1 に答える 1

5

Response L.ByteStringこれは怠惰とは関係ありませんが、Simple モジュールでResponse BodyReader得られる と TLS モジュールで得られるの違いによるものです。

BodyReaderaが であることに気付きましたIO ByteStringしかし、特に、次のバイトのチャンクで毎回繰り返すことができるアクションです。ファイルの最後にある場合を除いて、null バイト文字列を送信しないというプロトコルに従います。(BodyReaderと呼ばれていたかもしれませんChunkGetter)。bip以下はあなたが書いたようなものです: から / を抽出した後、BodyReaderそれを実行して最初のチャンクを取得し、それを出力します。しかし、より多くを得るためにアクションを繰り返さないので、この場合、創世記の最初のいくつかの章を見るだけです. 必要なのは、以下のようにチャンクを使い果たすためのループです。これにより、欽定訳聖書全体がコンソールに流出します。IO ByteStringResponsebop

{-# 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 を表す空の文字列を取得するまで、より多くのチャンクを取得するために戻り続けるため、ターミナルでは黙示録の最後まで出力されます。

これは単純な動作ですが、少し技術的です。BodyReader手書きの再帰のみを使用できます。しかし、http-clientライブラリの目的は、このようなことをhttp-conduit可能にすることです。の結果はwithResponsetypeResponse (ConduitM i ByteString m ())です。ConduitM i ByteString m ()バイトストリームのコンジットタイプです。このバイト ストリームにはファイル全体が含まれます。

http-client/http-conduitマテリアルの元の形では、Responseこのようなコンジットが含まれていました。のようなさまざまなストリーミング ライブラリで使用できるように、このBodyReader部分は後で分解されました。http-clientpipes

簡単な例を挙げると、streamingおよびstreaming-bytestringライブラリの対応する http 資料ではwithHTTP、タイプ の応答が得られますResponse (ByteString IO ())ByteString IO ()その名前が示すように、IO で発生するバイト ストリームのタイプです。ByteString Identity ()遅延バイト文字列 (事実上、チャンクの純粋なリスト) と同等です。ByteString IO ()この場合の will は、アポカリプスまでのバイトストリーム全体を表します。だからインポートで

 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

次に、アブラハムについて何かがわかります。

withHTTPforは、マテリアルを直接streaming-bytestring使用するために必要な再帰ループを隠しているだけです。これは、バイト文字列チャンクのストリームを として表す にあると同じであり、 と同じです。これらすべてのケースで、バイト ストリームを取得したら、手書きの再帰を使用せずに、ストリーミング IO フレームワークの典型的な方法で処理します。それらはすべてfromを使用してこれを行い、これがライブラリの主な目的でした。BodyReaderhttp-clientwithHTTPpipes-httpProducer ByteString IO ()http-conduitBodyReaderhttp-client

于 2017-01-06T02:49:59.173 に答える