2016-12-25 6 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 내가 내 데이터를 전송하는 데 사용하는 단지 사용자 정의 데이터 형식입니다.

r -> Controller usr 

및 I : 어떤이 될 것

r -> Handler usr 

인증 핸들러로, 나는 내 사용자 지정 처리기를 사용할 수 없습니다

문제는 내 AuthHandler 내가 구체적으로 기능을 이용해야한다는 것입니다 내 ConnectionPool에 서명 할 수 없기 때문에 통과 할 수있는 방법이 없습니다.

ConnPool -> r -> Handler usr 

글로벌 IO 상태를 사용하지 않고 서번트의 인증 처리기에 여분의 데이터를 전달하는 방법은 무엇입니까?

답변

7

AuthHandler 문맥에 넣은 최상위 수준에서 정의 할 필요는 없습니다! ... 좋은 지적입니다

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

을 여전히 그렇지 않은 : 당신은 당신이 만든 등 데이터베이스 연결에 액세스 할 수 있으므로 일반적으로, 당신은 main에서 그것을하고 싶은 것 인증 처리기에 사용자 지정 모나드를 사용할 수 있습니까? – Reygoch

+0

- 우리는 서명'Controller User'를'authenticate '할 수 있었고'let ctx = runReader (runController authenticate) env :를 보냈습니다. EmptyContext'. – user2141650