перехват исключений ввода-вывода в слуге - PullRequest
0 голосов
/ 19 февраля 2019

Я использую servant для простого JSON API, который позволяет создавать пользователей, чьи имена должны быть уникальными.Это обеспечивается уникальным ограничением в SQLite.У меня есть функция DB.saveUser :: UserReq -> IO Int, которая (что неудивительно) сохраняет пользователей в SQLite и возвращает сгенерированный идентификатор.Он выдаст SQLError ErrorConstraint _ _, если имя уже занято.Я хочу вернуть HTTP-код ответа 409, если это произойдет.Поэтому мой вопрос был бы: есть ли способ поймать SQLError в монаде обработчика?Если нет, то какой самый чистый способ достичь того, что я ищу?Я думал о том, чтобы заставить DB.saveUser вернуть Maybe Int, но почему-то я думаю, что должно быть лучшее решение.

createUser :: UserReq -> Handler (Headers '[Header "Location" Text] NoContent)
createUser ur = do id <- liftIO (DB.saveUser ur)
                   return . addHeader (T.pack ("/user/" ++ show id)) $ NoContent

saveUser (UR.UserReq name) = withConnection database $ \conn ->
  do executeNamed conn "INSERT INTO users (name) VALUES (:name)" [":name" := name]
     fromIntegral <$> lastInsertRowId conn

1 Ответ

0 голосов
/ 19 февраля 2019

Слуга Handler - это оболочка нового типа:

newtype Handler a = Handler { runHandler' :: ExceptT ServantErr IO a }

внутри, есть ExceptT ServantErr, где ServantErr:

data ServantErr = ServantErr { errHTTPCode     :: Int
                             , errReasonPhrase :: String
                             , errBody         :: LBS.ByteString
                             , errHeaders      :: [HTTP.Header]
                             } deriving (Show, Eq, Read, Typeable)

Итак, вы можете запуститьваши операции с БД, например, try или, для обработки высвобождающих ресурсов: bracket, и сопоставьте ваши исключения из БД с ServantErr, чтобы получить нужный код ответа HTTP.

Как бросить ServantErrпосле перехвата исключения из БД: https://haskell -servant.readthedocs.io / en / stable / tutorial / Server.html # failing-through-servanterr

...