【问题标题】:Haskell Servant passing custom data to auth handlerHaskell Servant 将自定义数据传递给身份验证处理程序
【发布时间】:2016-12-25 10:25:29
【问题描述】:

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

这就是我定义我的自定义 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 状态的情况下将额外数据传递给servant 中的身份验证处理程序?

【问题讨论】:

    标签: database haskell authentication pool servant


    【解决方案1】:

    您放入上下文中的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
    

    【讨论】:

    • 仍然,不能使用自定义 monad 进行身份验证处理程序吗?
    • 是的——我们可以给authenticate签名Controller User,然后给let ctx = runReader (runController authenticate) env :. EmptyContext
    • mmm.. 是的,但是我必须将 env 传递给我的身份验证上下文和我的常规控制器。我正在使用enter (convertController env) serverRoutes 将我的Controllers 转换为Handlers,如果我想在我的堆栈中使用State,那么身份验证处理程序和我的常规处理程序的状态将不同步。
    • 是的,不过如果您想将状态从身份验证处理程序线程化到普通处理程序,您可以使用Requests Vault(或IORef)。
    • 您不能在处理程序中使用 State 来共享和修改来自不同处理程序或同一处理程序但在 2 个不同请求中的状态:使用 State 处理程序仅允许您读取/在给定请求的给定处理程序的一次运行中修改某些状态。关于问题本身:没有什么(还)可以让人们轻松调用enter 一次并将其应用于身份验证上下文和处理程序。这是两个非常独立的东西,上下文可能包含各种东西,其中一些我们不想应用这种转换。
    猜你喜欢
    • 2013-04-03
    • 1970-01-01
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多