2016-12-25 7 views
4

私はDBプールのようなデータをハンドラに簡単に渡すために(カスタムモナドを使用する前にfn引数として渡していました)カスタムモナドを使用しています。Haskell Servantは認証ハンドラにカスタムデータを渡します

これは私が私のカスタムモナドを定義した方法です:

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

このServerEnvironmentは、私は私のデータを運ぶために使用するだけのカスタムデータ型です。

問題は、私のAuthHandlerのために、私は特異的に機能を使用する必要があることです。

r -> Controller usr 

とI:認証ハンドラとして

r -> Handler usr 

、私は次のようになり、私のカスタムハンドラを使用することはできませんまた、ConnectionPoolに署名することができないので、私はConnectionPoolを渡す方法がありません。

ConnPool -> r -> Handler usr 

したがって、グローバルIO状態を使用せずに、サバントの認証ハンドラに余分なデータを渡すにはどうすればよいですか?

答えて

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 
+0

...良い点です... – Reygoch

+0

まだ、そうではありません認証ハンドラにカスタムモナドを使用することは可能ですか? – Reygoch

+0

これは、署名 'Controller User'を' authenticate'してから、 'let ctx = runReader(runController authenticate)env:。 EmptyContext'。 – user2141650

関連する問題