cookbook: add jsonerror section
This commit is contained in:
parent
6af38354d0
commit
9b73435d21
4 changed files with 76 additions and 0 deletions
|
@ -5,6 +5,7 @@ packages:
|
||||||
using-custom-monad/
|
using-custom-monad/
|
||||||
jwt-and-basic-auth/
|
jwt-and-basic-auth/
|
||||||
file-upload/
|
file-upload/
|
||||||
|
jsonerror/
|
||||||
structuring-apis/
|
structuring-apis/
|
||||||
https/
|
https/
|
||||||
pagination/
|
pagination/
|
||||||
|
|
|
@ -26,3 +26,4 @@ you name it!
|
||||||
jwt-and-basic-auth/JWTAndBasicAuth.lhs
|
jwt-and-basic-auth/JWTAndBasicAuth.lhs
|
||||||
file-upload/FileUpload.lhs
|
file-upload/FileUpload.lhs
|
||||||
pagination/Pagination.lhs
|
pagination/Pagination.lhs
|
||||||
|
jsonerror/Jsonerror.lhs
|
||||||
|
|
50
doc/cookbook/jsonerror/Jsonerror.lhs
Normal file
50
doc/cookbook/jsonerror/Jsonerror.lhs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# HTTP 4XX/5XX errors with JSON body
|
||||||
|
|
||||||
|
Common RESTful design pattern is to return
|
||||||
|
HTTP 4XX or 5XX errors with JSON as body content.
|
||||||
|
|
||||||
|
Servant offer such support via `MonadError` instance:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE DeriveAnyClass #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
|
||||||
|
import Servant
|
||||||
|
import GHC.Generics (Generic)
|
||||||
|
import Data.Aeson (ToJSON, encode)
|
||||||
|
import Data.Text (Text)
|
||||||
|
import Network.HTTP.Types (hContentType)
|
||||||
|
import Control.Monad.Except (MonadError)
|
||||||
|
|
||||||
|
|
||||||
|
throwJSONError :: (MonadError ServantErr m, ToJSON a) => ServantErr -> a -> m b
|
||||||
|
throwJSONError err json = throwError $ err
|
||||||
|
{ errBody = encode json
|
||||||
|
, errHeaders = [ jsonHeader ]
|
||||||
|
}
|
||||||
|
where
|
||||||
|
jsonHeader = ( hContentType
|
||||||
|
, "application/json;charset=utf-8" )
|
||||||
|
```
|
||||||
|
|
||||||
|
And simple usage with servant-server:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
data JSONError = JSONError
|
||||||
|
{ error :: Text
|
||||||
|
} deriving (Generic, ToJSON)
|
||||||
|
|
||||||
|
handler :: Handler NoContent
|
||||||
|
handler = throwJSONError err400 $ JSONError "test"
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
There are (at least) two shortcomings with this approach:
|
||||||
|
|
||||||
|
1) [throwError sacrifices content negotiation](https://github.com/haskell-servant/servant/issues/732)
|
||||||
|
|
||||||
|
2) Errors are not part of the type-level API safety, there are solutions like [servant-checked-exceptions](https://github.com/cdepillabout/servant-checked-exceptions) but they don't implement all HasServer, etc instances.
|
24
doc/cookbook/jsonerror/jsonerror.cabal
Normal file
24
doc/cookbook/jsonerror/jsonerror.cabal
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
name: cookbook-jsonerror
|
||||||
|
version: 0.1
|
||||||
|
synopsis: Jsonerror with Servant example
|
||||||
|
homepage: http://haskell-servant.readthedocs.org/
|
||||||
|
license: BSD3
|
||||||
|
author: Servant Contributors
|
||||||
|
maintainer: haskell-servant-maintainers@googlegroups.com
|
||||||
|
build-type: Simple
|
||||||
|
cabal-version: >=1.10
|
||||||
|
|
||||||
|
executable cookbook-jsonerror
|
||||||
|
if impl(ghc < 7.10.1)
|
||||||
|
buildable: False
|
||||||
|
main-is: Jsonerror.lhs
|
||||||
|
build-depends: base == 4.*
|
||||||
|
, aeson
|
||||||
|
, servant
|
||||||
|
, servant-server
|
||||||
|
, http-types
|
||||||
|
, mtl
|
||||||
|
, text
|
||||||
|
default-language: Haskell2010
|
||||||
|
ghc-options: -Wall -pgmL markdown-unlit
|
||||||
|
build-tool-depends: markdown-unlit:markdown-unlit
|
Loading…
Reference in a new issue