Haskell Servant将自定义数据传递给auth处理程序

时间:2016-12-25 10:25:30

标签: database haskell authentication pool servant

我正在使用自定义monad(带阅读器)轻松地将数据库池等数据传递给我的处理程序(在使用我用来将连接作为fn参数传递的自定义monad之前)。

这就是我定义自定义monad的方式:

newtype Controller a = Controller
    { runController :: ReaderT ServerEnvironment Handler a
    } deriving ( Functor, Applicative, Monad, MonadReader ServerEnvironment, 
                 MonadError ServantErr, MonadIO )

这个ServerEnvironment只是我用来传输数据的自定义数据类型。

问题是,对于我的AuthHandler,我必须专门使用函数:

r -> Handler usr

作为身份验证处理程序,我不能使用我的自定义处理程序:

r -> Controller usr

我也无法传递ConnectionPool,因为签名不能是:

ConnPool -> r -> Handler usr

那么,如何在不使用全局IO状态的情况下将额外数据传递给服务方中的身份验证处理程序?

1 个答案:

答案 0 :(得分:7)

您在上下文中添加的AuthHandler不必在顶层定义!通常,您希望在main中执行此操作,以便您可以访问您已创建的数据库连接等:

type API = 
  ... :<|> (AuthProtect "myProtection" :> ...) :<|> ...

type instance AuthServerData (AuthProtect "myProtection") = User

server :: ServerEnvironment -> Server API
server env = ...

setupEnv :: IO ServerEnvironment
setupEnv = ..

-- This is essentially a 'Controller'.
authenticate :: ServerEnvironment -> Handler User
authenticate conn = ...

main :: IO ()
main = do
  env <- setupEnv
  -- Now, because we have access to the env, we can turn our
  -- 'authenticate' into the right type before putting it
  -- in the context
  let ctx = authenticate env :. EmptyContext
  run 8080 $ serveWithContext myAPI (server conn) ctx