在http-conduit中通过Maybe处理404



使用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表格中回答的,因此没有显示出研究的努力。

这可以通过使用与官方示例类似的自定义checkStatus实现。

如果响应状态码是2xx或404,我们将声明checkStatus200通过。如果没有通过,它调用默认的checkStatus函数来抛出相应的异常。

在使用checkStatus200调用Request调用httpLbs之后,我们可以检查状态码并返回Just响应码或Nothing

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

相关内容

  • 没有找到相关文章

最新更新