在happstack-server中读取请求体两次

时间:2018-04-27 10:54:14

标签: haskell httprequest happstack

我在happstack-server应用程序中读取正文两次有问题。

我已经嵌入了一个用于用户身份验证的库(happstack-authenticate)。 happstack-authenticate有一个JSON-Api来管理用户,我在调用JSON-Api后尝试访问同一个请求体。不幸的是,这个libray使用了导致身体崩溃的方法takeRequestBody,所以在此之后我无法访问请求体。在调用库之前尝试访问正文只会转移问题,因为我也使用了takeRequestBody。

takeRequestBody删除内容的原因是因为它基于tryTakeMVAR

我的问题有解决方法吗?我需要两次进入身体还是有另一种解决方案?或者也许还有另一种方法来阅读不会破坏身体的身体?

用于演示问题的简单代码:

module Test where

import Data.Data                     ( Data, Typeable )
import Happstack.Server 
import Happstack.Authenticate.Core
import Data.Acid                     ( AcidState )
import Web.Routes                    ( RouteT(..) )
import Control.Monad.IO.Class        ( liftIO )
import qualified Data.ByteString.Lazy.Char8 as L


getBody :: RouteT AuthenticateURL (ServerPartT IO) L.ByteString
getBody = do
    req  <- askRq
    body <- liftIO $ takeRequestBody req
    case body of
        Just rqbody -> return . unBody $ rqbody
        Nothing     -> return (L.pack "")


route :: AcidState AuthenticateState -> (AuthenticateURL -> RouteT AuthenticateURL (ServerPartT IO) Response)
        -> AuthenticateURL -> RouteT AuthenticateURL (ServerPartT IO) Response
route authenticateState routeAuthenticate authenticateURL =
    do
        --routeAuthenticate is a routing function from Happstack.Authenticate
        routeAuthenticate authenticateURL
        body <- getBody
        ok $ toResponse body

1 个答案:

答案 0 :(得分:1)

我实现了一种变通方法,它使用函数tryReadMVar代替tryTakeMVAR。有了这个功能,我可以阅读身体而不会破坏它继续进程

peekRequestBody :: (MonadIO m) => Request -> m (Maybe RqBody)
peekRequestBody rq = liftIO $ tryReadMVar (rqBody rq)

getBody :: RouteT AuthenticateURL (ServerPartT IO) L.ByteString
getBody = do
    req  <- askRq
    body <- liftIO $ peekRequestBody req
    case body of
        Just rqbody -> return . unBody $ rqbody
        Nothing     -> return (L.pack "")