2016-12-25 4 views
4

Я использую обычную монаду (с читателем), чтобы легко передавать данные, такие как пул БД, моим обработчикам (перед использованием пользовательской монады, которую я использовал для передачи соединения в качестве аргумента fn).Haskell Servant, передающий пользовательские данные обработчику auth

Это, как я определил свои собственные монады:

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 

Итак, как передать дополнительные данные обработчику аутентификации в servant без использования глобального состояния 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

Это - мы могли бы дать 'authenticate' подпись' Controller User', а затем 'let ctx = runReader (runController authenticate) env:. EmptyContext'. – user2141650

 Смежные вопросы

  • Нет связанных вопросов^_^