在仆人中捕获 IO 异常
catching IO exceptions in servant
我使用 servant
作为一个简单的 JSON api,它允许您创建名称必须唯一的用户。这是由 SQLite 中的唯一约束强制执行的。我有一个函数 DB.saveUser :: UserReq -> IO Int
可以(不出所料)将用户保存到 SQLite 并 returns 生成的 id。如果该名称已被使用,它将抛出 SQLError ErrorConstraint _ _
。如果发生这种情况,我想 return HTTP 响应代码 409。所以我的问题是,有什么方法可以在 Handler Monad 中捕获 SQLError
吗?如果没有,实现我正在寻找的最干净的方法是什么?我考虑过将 DB.saveUser
return 设为 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
Servant 的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
我使用 servant
作为一个简单的 JSON api,它允许您创建名称必须唯一的用户。这是由 SQLite 中的唯一约束强制执行的。我有一个函数 DB.saveUser :: UserReq -> IO Int
可以(不出所料)将用户保存到 SQLite 并 returns 生成的 id。如果该名称已被使用,它将抛出 SQLError ErrorConstraint _ _
。如果发生这种情况,我想 return HTTP 响应代码 409。所以我的问题是,有什么方法可以在 Handler Monad 中捕获 SQLError
吗?如果没有,实现我正在寻找的最干净的方法是什么?我考虑过将 DB.saveUser
return 设为 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
Servant 的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