我创建了一个自定义的servant处理程序
type ServiceSet = TVar (M.Map String [MicroService])
type LocalHandler = ReaderT ServiceSet IO
但我没有找到一种方法在以下功能中将404未找到的状态代码响应给客户端:
getService :: String -> LocalHandler MicroService
getService sn = do
tvar <- ask
ms <- liftIO $ do
sl <- atomically $ do
sm <- readTVar tvar
return $ case M.lookup sn sm of
Nothing -> []
Just sl -> sl
let n = length sl
i <- randomRIO (0, n - 1)
return $ if n == 0
then Nothing
else Just . head . drop i $ sl
case ms of
Nothing -> ??? -- throwError err404
Just ms' -> return ms'
如何在???
中发送404状态代码?
答案 0 :(得分:4)
您需要将ExceptT
添加到您的monad变换堆栈中。现在,仅使用ReaderT
,就无法编码抛出错误的概念。
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
module Lib where
import Control.Monad.Except
import Control.Monad.Reader
import Data.Maybe
import Data.Map
import GHC.Conc
import Prelude hiding (lookup)
import Servant.API
import Servant.Server
import System.Random
type API =
Capture "name" String :> Get '[JSON] Int
type World =
TVar (Map String [Int])
type Effects =
ExceptT ServantErr (ReaderT World IO)
server :: World -> Server API
server world =
enter (Nat transform) get
where
transform :: Effects a -> ExceptT ServantErr IO a
transform (ExceptT foo) =
ExceptT $ runReaderT foo world
get :: String -> Effects Int
get sn = do
tvar <- ask
ms <- liftIO $ do
sl <- atomically $ do
sm <- readTVar tvar
return (fromMaybe [] (lookup sn sm))
let n = length sl
i <- randomRIO (0, n - 1)
return $ if n == 0
then Nothing
else Just . head . drop i $ sl
case ms of
Nothing ->
throwError err404
Just ms' ->
return ms'
使用ExceptT ServantErr . ReaderT (TVar ...)
,然后您可以throwError err404
,Servant将捕获并使用它来返回HTTP 404.然后,自然转换ExceptT ServantErr . ReaderT (TVar ...) :~> ExceptT ServantErr
将需要打开并重新包装以释放读者效应。总而言之,代码并不多。