1

を使用しhttp-conduitて、次のセマンティクスを実装する HTTP URL をダウンロードします (結果はIO (Maybe LB.ByteString)):

  1. HTTP 応答コードが 2xx の場合Just、応答本文を返す
  2. HTTP レスポンス コードが 404 の場合は、Nothing
  3. 応答コードがリダイレクトを示している場合は、標準の http-conduit 設定に従ってください
  4. その他の応答コードについては、StatusCodeException.

それ以上のライブラリとその依存関係httpLbsなしでそれを行うにはどうすればよいですか?http-conduit

注: この質問は Q&A 形式で回答されているため、意図的に研究努力を示していません。

4

1 に答える 1

2

これは、公式の例checkStatusの 1 つに似たカスタムを使用することで可能になります。

応答ステータス コードが 2xx または 404 の場合、どちらがパスするかを宣言します。checkStatus200パスしない場合は、デフォルトcheckStatus関数を呼び出して適切な例外をスローします。

usingで呼び出しhttpLbsた後、ステータス コードを確認して、レスポンス コードまたはを返すことができます。RequestcheckStatus200JustNothing

import Data.Conduit.Binary (sinkFile)
import Network.HTTP.Types.Status (Status(..))
import Network.HTTP.Conduit
import qualified Data.Conduit as C
import Network
import Data.Default (def)
import qualified Data.ByteString.Lazy as LB

-- | @checkStatus@ implementation that accepts 
--   2xx status codes and 404. Calls default implementation
--   on other status codes (i.e. throws exception)
checkStatus200 st@(Status sc _) rh cj =
    if (200 <= sc && sc < 300) || sc == 404
        then Nothing
        else (checkStatus def) st rh cj

-- | Download a HTTP link, returning @Nothing@ on 404 status code
downloadCatch404 :: String
                 -> IO (Maybe LB.ByteString)
downloadCatch404 url = withSocketsDo $ do
    request <- parseUrl url
    let request' = request { checkStatus = checkStatus200 }
    res <- withManager $ httpLbs request'
    let status =  statusCode . responseStatus $ res
    -- Return Nothing if status code == 404
    return $ if status == 404
        then Nothing
        else Just $ responseBody res
于 2014-07-30T22:11:10.430 に答える