Merge pull request #1131 from phadej/error-renaming
Rename ServantError to ClientError, ServantErr to ServerError
This commit is contained in:
commit
3db3d38e14
25 changed files with 162 additions and 166 deletions
12
.travis.yml
12
.travis.yml
|
@ -87,9 +87,7 @@ install:
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/db-sqlite-simple\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/db-sqlite-simple\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/file-upload\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/file-upload\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/generic\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/generic\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/hoist-server-with-context\"\\n' >> cabal.project ; fi"
|
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/https\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/https\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/jwt-and-basic-auth\"\\n' >> cabal.project ; fi"
|
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/testing\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/testing\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/structuring-apis\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/structuring-apis\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/using-custom-monad\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"doc/cookbook/using-custom-monad\"\\n' >> cabal.project ; fi"
|
||||||
|
@ -106,7 +104,7 @@ install:
|
||||||
- "echo 'reorder-goals: True' >> cabal.project"
|
- "echo 'reorder-goals: True' >> cabal.project"
|
||||||
- "echo 'optimization: False' >> cabal.project "
|
- "echo 'optimization: False' >> cabal.project "
|
||||||
- touch cabal.project.local
|
- touch cabal.project.local
|
||||||
- "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(cookbook-basic-auth|cookbook-basic-streaming|cookbook-curl-mock|cookbook-db-postgres-pool|cookbook-db-sqlite-simple|cookbook-file-upload|cookbook-generic|cookbook-hoist-server-with-context|cookbook-https|cookbook-jwt-and-basic-auth|cookbook-structuring-apis|cookbook-testing|cookbook-using-custom-monad|cookbook-using-free-client|servant|servant-client|servant-client-core|servant-conduit|servant-docs|servant-foreign|servant-http-streams|servant-machines|servant-pipes|servant-server|tutorial)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
|
- "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(cookbook-basic-auth|cookbook-basic-streaming|cookbook-curl-mock|cookbook-db-postgres-pool|cookbook-db-sqlite-simple|cookbook-file-upload|cookbook-generic|cookbook-https|cookbook-structuring-apis|cookbook-testing|cookbook-using-custom-monad|cookbook-using-free-client|servant|servant-client|servant-client-core|servant-conduit|servant-docs|servant-foreign|servant-http-streams|servant-machines|servant-pipes|servant-server|tutorial)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
|
||||||
- cat cabal.project || true
|
- cat cabal.project || true
|
||||||
- cat cabal.project.local || true
|
- cat cabal.project.local || true
|
||||||
- if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi
|
- if [ -f "servant/configure.ac" ]; then (cd "servant" && autoreconf -i); fi
|
||||||
|
@ -127,15 +125,13 @@ install:
|
||||||
- if [ -f "doc/cookbook/db-sqlite-simple/configure.ac" ]; then (cd "doc/cookbook/db-sqlite-simple" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/db-sqlite-simple/configure.ac" ]; then (cd "doc/cookbook/db-sqlite-simple" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/file-upload/configure.ac" ]; then (cd "doc/cookbook/file-upload" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/file-upload/configure.ac" ]; then (cd "doc/cookbook/file-upload" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/generic/configure.ac" ]; then (cd "doc/cookbook/generic" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/generic/configure.ac" ]; then (cd "doc/cookbook/generic" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/hoist-server-with-context/configure.ac" ]; then (cd "doc/cookbook/hoist-server-with-context" && autoreconf -i); fi
|
|
||||||
- if [ -f "doc/cookbook/https/configure.ac" ]; then (cd "doc/cookbook/https" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/https/configure.ac" ]; then (cd "doc/cookbook/https" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/jwt-and-basic-auth/configure.ac" ]; then (cd "doc/cookbook/jwt-and-basic-auth" && autoreconf -i); fi
|
|
||||||
- if [ -f "doc/cookbook/testing/configure.ac" ]; then (cd "doc/cookbook/testing" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/testing/configure.ac" ]; then (cd "doc/cookbook/testing" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/structuring-apis/configure.ac" ]; then (cd "doc/cookbook/structuring-apis" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/structuring-apis/configure.ac" ]; then (cd "doc/cookbook/structuring-apis" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/using-custom-monad/configure.ac" ]; then (cd "doc/cookbook/using-custom-monad" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/using-custom-monad/configure.ac" ]; then (cd "doc/cookbook/using-custom-monad" && autoreconf -i); fi
|
||||||
- if [ -f "doc/cookbook/using-free-client/configure.ac" ]; then (cd "doc/cookbook/using-free-client" && autoreconf -i); fi
|
- if [ -f "doc/cookbook/using-free-client/configure.ac" ]; then (cd "doc/cookbook/using-free-client" && autoreconf -i); fi
|
||||||
- rm -f cabal.project.freeze
|
- rm -f cabal.project.freeze
|
||||||
- rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-client-core"/dist "servant-http-streams"/dist "servant-docs"/dist "servant-foreign"/dist "servant-server"/dist "doc/tutorial"/dist "servant-machines"/dist "servant-conduit"/dist "servant-pipes"/dist "doc/cookbook/basic-auth"/dist "doc/cookbook/curl-mock"/dist "doc/cookbook/basic-streaming"/dist "doc/cookbook/db-postgres-pool"/dist "doc/cookbook/db-sqlite-simple"/dist "doc/cookbook/file-upload"/dist "doc/cookbook/generic"/dist "doc/cookbook/hoist-server-with-context"/dist "doc/cookbook/https"/dist "doc/cookbook/jwt-and-basic-auth"/dist "doc/cookbook/testing"/dist "doc/cookbook/structuring-apis"/dist "doc/cookbook/using-custom-monad"/dist "doc/cookbook/using-free-client"/dist
|
- rm -rf .ghc.environment.* "servant"/dist "servant-client"/dist "servant-client-core"/dist "servant-http-streams"/dist "servant-docs"/dist "servant-foreign"/dist "servant-server"/dist "doc/tutorial"/dist "servant-machines"/dist "servant-conduit"/dist "servant-pipes"/dist "doc/cookbook/basic-auth"/dist "doc/cookbook/curl-mock"/dist "doc/cookbook/basic-streaming"/dist "doc/cookbook/db-postgres-pool"/dist "doc/cookbook/db-sqlite-simple"/dist "doc/cookbook/file-upload"/dist "doc/cookbook/generic"/dist "doc/cookbook/https"/dist "doc/cookbook/testing"/dist "doc/cookbook/structuring-apis"/dist "doc/cookbook/using-custom-monad"/dist "doc/cookbook/using-free-client"/dist
|
||||||
- DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
|
- DISTDIR=$(mktemp -d /tmp/dist-test.XXXX)
|
||||||
|
|
||||||
# Here starts the actual work to be performed for the package under test;
|
# Here starts the actual work to be performed for the package under test;
|
||||||
|
@ -169,9 +165,7 @@ script:
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-db-sqlite-simple-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-db-sqlite-simple-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-file-upload-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-file-upload-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-generic-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-generic-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-hoist-server-with-context-*/*.cabal\"\\n' >> cabal.project ; fi"
|
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-https-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-https-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-jwt-and-basic-auth-*/*.cabal\"\\n' >> cabal.project ; fi"
|
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-testing-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-testing-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-structuring-apis-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-structuring-apis-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-using-custom-monad-*/*.cabal\"\\n' >> cabal.project ; fi"
|
- "if [ $HCNUMVER -eq 80404 ] || [ $HCNUMVER -eq 80603 ] ; then printf 'packages: \"cookbook-using-custom-monad-*/*.cabal\"\\n' >> cabal.project ; fi"
|
||||||
|
@ -188,7 +182,7 @@ script:
|
||||||
- "echo 'reorder-goals: True' >> cabal.project"
|
- "echo 'reorder-goals: True' >> cabal.project"
|
||||||
- "echo 'optimization: False' >> cabal.project "
|
- "echo 'optimization: False' >> cabal.project "
|
||||||
- touch cabal.project.local
|
- touch cabal.project.local
|
||||||
- "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(cookbook-basic-auth|cookbook-basic-streaming|cookbook-curl-mock|cookbook-db-postgres-pool|cookbook-db-sqlite-simple|cookbook-file-upload|cookbook-generic|cookbook-hoist-server-with-context|cookbook-https|cookbook-jwt-and-basic-auth|cookbook-structuring-apis|cookbook-testing|cookbook-using-custom-monad|cookbook-using-free-client|servant|servant-client|servant-client-core|servant-conduit|servant-docs|servant-foreign|servant-http-streams|servant-machines|servant-pipes|servant-server|tutorial)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
|
- "for pkg in $($HCPKG list --simple-output); do echo $pkg | sed 's/-[^-]*$//' | grep -vE -- '^(cookbook-basic-auth|cookbook-basic-streaming|cookbook-curl-mock|cookbook-db-postgres-pool|cookbook-db-sqlite-simple|cookbook-file-upload|cookbook-generic|cookbook-https|cookbook-structuring-apis|cookbook-testing|cookbook-using-custom-monad|cookbook-using-free-client|servant|servant-client|servant-client-core|servant-conduit|servant-docs|servant-foreign|servant-http-streams|servant-machines|servant-pipes|servant-server|tutorial)$' | sed 's/^/constraints: /' | sed 's/$/ installed/' >> cabal.project.local; done"
|
||||||
- cat cabal.project || true
|
- cat cabal.project || true
|
||||||
- cat cabal.project.local || true
|
- cat cabal.project.local || true
|
||||||
- echo -en 'travis_fold:end:unpack\\r'
|
- echo -en 'travis_fold:end:unpack\\r'
|
||||||
|
|
|
@ -21,11 +21,11 @@ packages:
|
||||||
doc/cookbook/db-sqlite-simple
|
doc/cookbook/db-sqlite-simple
|
||||||
doc/cookbook/file-upload
|
doc/cookbook/file-upload
|
||||||
doc/cookbook/generic
|
doc/cookbook/generic
|
||||||
doc/cookbook/hoist-server-with-context
|
-- doc/cookbook/hoist-server-with-context
|
||||||
doc/cookbook/https
|
doc/cookbook/https
|
||||||
doc/cookbook/jwt-and-basic-auth/
|
-- doc/cookbook/jwt-and-basic-auth/
|
||||||
-- doc/cookbook/pagination
|
-- doc/cookbook/pagination
|
||||||
-- doc/cookbook/sentry
|
-- doc/cookbook/sentry
|
||||||
doc/cookbook/testing
|
doc/cookbook/testing
|
||||||
doc/cookbook/structuring-apis
|
doc/cookbook/structuring-apis
|
||||||
doc/cookbook/using-custom-monad
|
doc/cookbook/using-custom-monad
|
||||||
|
|
|
@ -234,7 +234,7 @@ clientEnv esHost esPort = do
|
||||||
manager <- newManager defaultManagerSettings
|
manager <- newManager defaultManagerSettings
|
||||||
pure $ mkClientEnv manager baseUrl
|
pure $ mkClientEnv manager baseUrl
|
||||||
|
|
||||||
runSearchClient :: Text -> Text -> ClientM a -> IO (Either ServantError a)
|
runSearchClient :: Text -> Text -> ClientM a -> IO (Either ClientError a)
|
||||||
runSearchClient esHost esPort = (clientEnv esHost esPort >>=) . runClientM
|
runSearchClient esHost esPort = (clientEnv esHost esPort >>=) . runClientM
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ docServer esHost esPort = getDocById esHost esPort
|
||||||
-- actions
|
-- actions
|
||||||
getDocById :: Text -> Text -> Integer -> Handler Value
|
getDocById :: Text -> Text -> Integer -> Handler Value
|
||||||
getDocById esHost esPort docId = do
|
getDocById esHost esPort docId = do
|
||||||
-- Our Servant Client function returns Either ServantError Value here:
|
-- Our Servant Client function returns Either ClientError Value here:
|
||||||
docRes <- liftIO $ runSearchClient esHost esPort (getDocument docId)
|
docRes <- liftIO $ runSearchClient esHost esPort (getDocument docId)
|
||||||
case docRes of
|
case docRes of
|
||||||
Left err -> throwError $ err404 { errBody = "Failed looking up content" }
|
Left err -> throwError $ err404 { errBody = "Failed looking up content" }
|
||||||
|
|
|
@ -599,7 +599,7 @@ $ curl -H 'Accept: text/html' http://localhost:8081/persons
|
||||||
|
|
||||||
## The `Handler` monad
|
## The `Handler` monad
|
||||||
|
|
||||||
At the heart of the handlers is the monad they run in, namely a newtype `Handler` around `ExceptT ServantErr IO`
|
At the heart of the handlers is the monad they run in, namely a newtype `Handler` around `ExceptT ServerErroror IO`
|
||||||
([haddock documentation for `ExceptT`](http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#t:ExceptT)).
|
([haddock documentation for `ExceptT`](http://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#t:ExceptT)).
|
||||||
One might wonder: why this monad? The answer is that it is the
|
One might wonder: why this monad? The answer is that it is the
|
||||||
simplest monad with the following properties:
|
simplest monad with the following properties:
|
||||||
|
@ -617,7 +617,7 @@ newtype ExceptT e m a = ExceptT (m (Either e a))
|
||||||
```
|
```
|
||||||
|
|
||||||
In short, this means that a handler of type `Handler a` is simply
|
In short, this means that a handler of type `Handler a` is simply
|
||||||
equivalent to a computation of type `IO (Either ServantErr a)`, that is, an IO
|
equivalent to a computation of type `IO (Either ServerError a)`, that is, an IO
|
||||||
action that either returns an error or a result.
|
action that either returns an error or a result.
|
||||||
|
|
||||||
The module [`Control.Monad.Except`](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#t:ExceptT)
|
The module [`Control.Monad.Except`](https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-Except.html#t:ExceptT)
|
||||||
|
@ -660,16 +660,16 @@ server5 = do
|
||||||
return (FileContent filecontent)
|
return (FileContent filecontent)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Failing, through `ServantErr`
|
### Failing, through `ServerError`
|
||||||
|
|
||||||
If you want to explicitly fail at providing the result promised by an endpoint
|
If you want to explicitly fail at providing the result promised by an endpoint
|
||||||
using the appropriate HTTP status code (not found, unauthorized, etc) and some
|
using the appropriate HTTP status code (not found, unauthorized, etc) and some
|
||||||
error message, all you have to do is use the `throwError` function mentioned above
|
error message, all you have to do is use the `throwError` function mentioned above
|
||||||
and provide it with the appropriate value of type `ServantErr`, which is
|
and provide it with the appropriate value of type `ServerError`, which is
|
||||||
defined as:
|
defined as:
|
||||||
|
|
||||||
``` haskell ignore
|
``` haskell ignore
|
||||||
data ServantErr = ServantErr
|
data ServerError = ServerError
|
||||||
{ errHTTPCode :: Int
|
{ errHTTPCode :: Int
|
||||||
, errReasonPhrase :: String
|
, errReasonPhrase :: String
|
||||||
, errBody :: ByteString -- lazy bytestring
|
, errBody :: ByteString -- lazy bytestring
|
||||||
|
@ -685,7 +685,7 @@ use record update syntax:
|
||||||
failingHandler :: Handler ()
|
failingHandler :: Handler ()
|
||||||
failingHandler = throwError myerr
|
failingHandler = throwError myerr
|
||||||
|
|
||||||
where myerr :: ServantErr
|
where myerr :: ServerError
|
||||||
myerr = err503 { errBody = "Sorry dear user." }
|
myerr = err503 { errBody = "Sorry dear user." }
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ module Servant.Client.Core
|
||||||
, AuthClientData
|
, AuthClientData
|
||||||
|
|
||||||
-- * Generic Client
|
-- * Generic Client
|
||||||
, ServantError(..)
|
, ClientError(..)
|
||||||
, EmptyClient(..)
|
, EmptyClient(..)
|
||||||
|
|
||||||
-- * Response
|
-- * Response
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
module Servant.Client.Core.ClientError (
|
module Servant.Client.Core.ClientError (
|
||||||
ServantError (..),
|
ClientError (..),
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude ()
|
import Prelude ()
|
||||||
|
@ -42,7 +42,7 @@ import Servant.Client.Core.Response
|
||||||
-- | A type representing possible errors in a request
|
-- | A type representing possible errors in a request
|
||||||
--
|
--
|
||||||
-- Note that this type substantially changed in 0.12.
|
-- Note that this type substantially changed in 0.12.
|
||||||
data ServantError =
|
data ClientError =
|
||||||
-- | The server returned an error response including the
|
-- | The server returned an error response including the
|
||||||
-- failing request. 'requestPath' includes the 'BaseUrl' and the
|
-- failing request. 'requestPath' includes the 'BaseUrl' and the
|
||||||
-- path of the request.
|
-- path of the request.
|
||||||
|
@ -57,7 +57,7 @@ data ServantError =
|
||||||
| ConnectionError SomeException
|
| ConnectionError SomeException
|
||||||
deriving (Show, Generic, Typeable)
|
deriving (Show, Generic, Typeable)
|
||||||
|
|
||||||
instance Eq ServantError where
|
instance Eq ClientError where
|
||||||
FailureResponse req res == FailureResponse req' res' = req == req' && res == res'
|
FailureResponse req res == FailureResponse req' res' = req == req' && res == res'
|
||||||
DecodeFailure t r == DecodeFailure t' r' = t == t' && r == r'
|
DecodeFailure t r == DecodeFailure t' r' = t == t' && r == r'
|
||||||
UnsupportedContentType mt r == UnsupportedContentType mt' r' = mt == mt' && r == r'
|
UnsupportedContentType mt r == UnsupportedContentType mt' r' = mt == mt' && r == r'
|
||||||
|
@ -74,11 +74,11 @@ instance Eq ServantError where
|
||||||
InvalidContentTypeHeader {} == _ = False
|
InvalidContentTypeHeader {} == _ = False
|
||||||
ConnectionError {} == _ = False
|
ConnectionError {} == _ = False
|
||||||
|
|
||||||
instance Exception ServantError
|
instance Exception ClientError
|
||||||
|
|
||||||
-- | Note: an exception in 'ConnectionError' might not be evaluated fully,
|
-- | Note: an exception in 'ConnectionError' might not be evaluated fully,
|
||||||
-- We only 'rnf' its 'show'ed value.
|
-- We only 'rnf' its 'show'ed value.
|
||||||
instance NFData ServantError where
|
instance NFData ClientError where
|
||||||
rnf (FailureResponse req res) = rnf req `seq` rnf res
|
rnf (FailureResponse req res) = rnf req `seq` rnf res
|
||||||
rnf (DecodeFailure err res) = rnf err `seq` rnf res
|
rnf (DecodeFailure err res) = rnf err `seq` rnf res
|
||||||
rnf (UnsupportedContentType mt' res) = mediaTypeRnf mt' `seq` rnf res
|
rnf (UnsupportedContentType mt' res) = mediaTypeRnf mt' `seq` rnf res
|
||||||
|
|
|
@ -254,7 +254,7 @@ instance {-# OVERLAPPING #-}
|
||||||
, requestAccept = fromList $ toList accept
|
, requestAccept = fromList $ toList accept
|
||||||
}
|
}
|
||||||
case mimeUnrender (Proxy :: Proxy ct) $ responseBody response of
|
case mimeUnrender (Proxy :: Proxy ct) $ responseBody response of
|
||||||
Left err -> throwServantError $ DecodeFailure (pack err) response
|
Left err -> throwClientError $ DecodeFailure (pack err) response
|
||||||
Right val -> return $ Headers
|
Right val -> return $ Headers
|
||||||
{ getResponse = val
|
{ getResponse = val
|
||||||
, getHeadersHList = buildHeadersTo . toList $ responseHeaders response
|
, getHeadersHList = buildHeadersTo . toList $ responseHeaders response
|
||||||
|
@ -662,7 +662,7 @@ checkContentTypeHeader response =
|
||||||
case lookup "Content-Type" $ toList $ responseHeaders response of
|
case lookup "Content-Type" $ toList $ responseHeaders response of
|
||||||
Nothing -> return $ "application"//"octet-stream"
|
Nothing -> return $ "application"//"octet-stream"
|
||||||
Just t -> case parseAccept t of
|
Just t -> case parseAccept t of
|
||||||
Nothing -> throwServantError $ InvalidContentTypeHeader response
|
Nothing -> throwClientError $ InvalidContentTypeHeader response
|
||||||
Just t' -> return t'
|
Just t' -> return t'
|
||||||
|
|
||||||
decodedAs :: forall ct a m. (MimeUnrender ct a, RunClient m)
|
decodedAs :: forall ct a m. (MimeUnrender ct a, RunClient m)
|
||||||
|
@ -670,9 +670,9 @@ decodedAs :: forall ct a m. (MimeUnrender ct a, RunClient m)
|
||||||
decodedAs response ct = do
|
decodedAs response ct = do
|
||||||
responseContentType <- checkContentTypeHeader response
|
responseContentType <- checkContentTypeHeader response
|
||||||
unless (any (matches responseContentType) accept) $
|
unless (any (matches responseContentType) accept) $
|
||||||
throwServantError $ UnsupportedContentType responseContentType response
|
throwClientError $ UnsupportedContentType responseContentType response
|
||||||
case mimeUnrender ct $ responseBody response of
|
case mimeUnrender ct $ responseBody response of
|
||||||
Left err -> throwServantError $ DecodeFailure (T.pack err) response
|
Left err -> throwClientError $ DecodeFailure (T.pack err) response
|
||||||
Right val -> return val
|
Right val -> return val
|
||||||
where
|
where
|
||||||
accept = toList $ contentTypes ct
|
accept = toList $ contentTypes ct
|
||||||
|
|
|
@ -12,7 +12,7 @@ module Servant.Client.Core.Reexport
|
||||||
, ResponseF(..)
|
, ResponseF(..)
|
||||||
|
|
||||||
-- * Data types
|
-- * Data types
|
||||||
, ServantError(..)
|
, ClientError(..)
|
||||||
, EmptyClient(..)
|
, EmptyClient(..)
|
||||||
|
|
||||||
-- * BaseUrl
|
-- * BaseUrl
|
||||||
|
|
|
@ -24,7 +24,7 @@ import Servant.Client.Core.Response
|
||||||
class Monad m => RunClient m where
|
class Monad m => RunClient m where
|
||||||
-- | How to make a request.
|
-- | How to make a request.
|
||||||
runRequest :: Request -> m Response
|
runRequest :: Request -> m Response
|
||||||
throwServantError :: ServantError -> m a
|
throwClientError :: ClientError -> m a
|
||||||
|
|
||||||
class RunClient m => RunStreamingClient m where
|
class RunClient m => RunStreamingClient m where
|
||||||
withStreamingRequest :: Request -> (StreamingResponse -> IO a) -> m a
|
withStreamingRequest :: Request -> (StreamingResponse -> IO a) -> m a
|
||||||
|
@ -38,9 +38,9 @@ class RunClient m => RunStreamingClient m where
|
||||||
-- Compare to 'RunClient'.
|
-- Compare to 'RunClient'.
|
||||||
data ClientF a
|
data ClientF a
|
||||||
= RunRequest Request (Response -> a)
|
= RunRequest Request (Response -> a)
|
||||||
| Throw ServantError
|
| Throw ClientError
|
||||||
deriving (Functor)
|
deriving (Functor)
|
||||||
|
|
||||||
instance ClientF ~ f => RunClient (Free f) where
|
instance ClientF ~ f => RunClient (Free f) where
|
||||||
runRequest req = liftF (RunRequest req id)
|
runRequest req = liftF (RunRequest req id)
|
||||||
throwServantError = liftF . Throw
|
throwClientError = liftF . Throw
|
||||||
|
|
|
@ -94,16 +94,16 @@ client api = api `clientIn` (Proxy :: Proxy ClientM)
|
||||||
--
|
--
|
||||||
-- NOTE: Does not support constant space streaming of the request body!
|
-- NOTE: Does not support constant space streaming of the request body!
|
||||||
newtype ClientM a = ClientM
|
newtype ClientM a = ClientM
|
||||||
{ runClientM' :: ReaderT ClientEnv (ExceptT ServantError IO) a }
|
{ runClientM' :: ReaderT ClientEnv (ExceptT ClientError IO) a }
|
||||||
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
||||||
, MonadReader ClientEnv, MonadError ServantError, MonadThrow
|
, MonadReader ClientEnv, MonadError ClientError, MonadThrow
|
||||||
, MonadCatch)
|
, MonadCatch)
|
||||||
|
|
||||||
instance MonadBase IO ClientM where
|
instance MonadBase IO ClientM where
|
||||||
liftBase = ClientM . liftBase
|
liftBase = ClientM . liftBase
|
||||||
|
|
||||||
instance MonadBaseControl IO ClientM where
|
instance MonadBaseControl IO ClientM where
|
||||||
type StM ClientM a = Either ServantError a
|
type StM ClientM a = Either ClientError a
|
||||||
|
|
||||||
liftBaseWith f = ClientM (liftBaseWith (\g -> f (g . runClientM')))
|
liftBaseWith f = ClientM (liftBaseWith (\g -> f (g . runClientM')))
|
||||||
|
|
||||||
|
@ -121,12 +121,12 @@ instance Exception StreamingNotSupportedException where
|
||||||
|
|
||||||
instance RunClient ClientM where
|
instance RunClient ClientM where
|
||||||
runRequest = performRequest
|
runRequest = performRequest
|
||||||
throwServantError = throwError
|
throwClientError = throwError
|
||||||
|
|
||||||
runClientMOrigin :: ClientM a -> ClientEnv -> IO (Either ServantError a)
|
runClientMOrigin :: ClientM a -> ClientEnv -> IO (Either ClientError a)
|
||||||
runClientMOrigin cm env = runExceptT $ flip runReaderT env $ runClientM' cm
|
runClientMOrigin cm env = runExceptT $ flip runReaderT env $ runClientM' cm
|
||||||
|
|
||||||
runClientM :: ClientM a -> IO (Either ServantError a)
|
runClientM :: ClientM a -> IO (Either ClientError a)
|
||||||
runClientM m = do
|
runClientM m = do
|
||||||
curLoc <- getWindowLocation
|
curLoc <- getWindowLocation
|
||||||
|
|
||||||
|
@ -298,7 +298,7 @@ foreign import javascript unsafe "$3.slice($1, $1 + $2)"
|
||||||
-- * inspecting the xhr response
|
-- * inspecting the xhr response
|
||||||
|
|
||||||
-- This function is only supposed to handle 'ConnectionError's. Other
|
-- This function is only supposed to handle 'ConnectionError's. Other
|
||||||
-- 'ServantError's are created in Servant.Client.Req.
|
-- 'ClientError's are created in Servant.Client.Req.
|
||||||
toResponse :: JSXMLHttpRequest -> ClientM Response
|
toResponse :: JSXMLHttpRequest -> ClientM Response
|
||||||
toResponse xhr = do
|
toResponse xhr = do
|
||||||
status <- liftIO $ getStatus xhr
|
status <- liftIO $ getStatus xhr
|
||||||
|
|
|
@ -120,16 +120,16 @@ hoistClient = hoistClientMonad (Proxy :: Proxy ClientM)
|
||||||
-- | @ClientM@ is the monad in which client functions run. Contains the
|
-- | @ClientM@ is the monad in which client functions run. Contains the
|
||||||
-- 'Client.Manager' and 'BaseUrl' used for requests in the reader environment.
|
-- 'Client.Manager' and 'BaseUrl' used for requests in the reader environment.
|
||||||
newtype ClientM a = ClientM
|
newtype ClientM a = ClientM
|
||||||
{ unClientM :: ReaderT ClientEnv (ExceptT ServantError IO) a }
|
{ unClientM :: ReaderT ClientEnv (ExceptT ClientError IO) a }
|
||||||
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
||||||
, MonadReader ClientEnv, MonadError ServantError, MonadThrow
|
, MonadReader ClientEnv, MonadError ClientError, MonadThrow
|
||||||
, MonadCatch)
|
, MonadCatch)
|
||||||
|
|
||||||
instance MonadBase IO ClientM where
|
instance MonadBase IO ClientM where
|
||||||
liftBase = ClientM . liftBase
|
liftBase = ClientM . liftBase
|
||||||
|
|
||||||
instance MonadBaseControl IO ClientM where
|
instance MonadBaseControl IO ClientM where
|
||||||
type StM ClientM a = Either ServantError a
|
type StM ClientM a = Either ClientError a
|
||||||
|
|
||||||
liftBaseWith f = ClientM (liftBaseWith (\g -> f (g . unClientM)))
|
liftBaseWith f = ClientM (liftBaseWith (\g -> f (g . unClientM)))
|
||||||
|
|
||||||
|
@ -141,9 +141,9 @@ instance Alt ClientM where
|
||||||
|
|
||||||
instance RunClient ClientM where
|
instance RunClient ClientM where
|
||||||
runRequest = performRequest
|
runRequest = performRequest
|
||||||
throwServantError = throwError
|
throwClientError = throwError
|
||||||
|
|
||||||
runClientM :: ClientM a -> ClientEnv -> IO (Either ServantError a)
|
runClientM :: ClientM a -> ClientEnv -> IO (Either ClientError a)
|
||||||
runClientM cm env = runExceptT $ flip runReaderT env $ unClientM cm
|
runClientM cm env = runExceptT $ flip runReaderT env $ unClientM cm
|
||||||
|
|
||||||
performRequest :: Request -> ClientM Response
|
performRequest :: Request -> ClientM Response
|
||||||
|
@ -197,7 +197,7 @@ performRequest req = do
|
||||||
fReq = Client.hrFinalRequest responses
|
fReq = Client.hrFinalRequest responses
|
||||||
fRes = Client.hrFinalResponse responses
|
fRes = Client.hrFinalResponse responses
|
||||||
|
|
||||||
mkFailureResponse :: BaseUrl -> Request -> ResponseF BSL.ByteString -> ServantError
|
mkFailureResponse :: BaseUrl -> Request -> ResponseF BSL.ByteString -> ClientError
|
||||||
mkFailureResponse burl request =
|
mkFailureResponse burl request =
|
||||||
FailureResponse (bimap (const ()) f request)
|
FailureResponse (bimap (const ()) f request)
|
||||||
where
|
where
|
||||||
|
@ -270,7 +270,7 @@ requestToClientRequest burl r = Client.defaultRequest
|
||||||
Http -> False
|
Http -> False
|
||||||
Https -> True
|
Https -> True
|
||||||
|
|
||||||
catchConnectionError :: IO a -> IO (Either ServantError a)
|
catchConnectionError :: IO a -> IO (Either ClientError a)
|
||||||
catchConnectionError action =
|
catchConnectionError action =
|
||||||
catch (Right <$> action) $ \e ->
|
catch (Right <$> action) $ \e ->
|
||||||
pure . Left . ConnectionError $ SomeException (e :: Client.HttpException)
|
pure . Left . ConnectionError $ SomeException (e :: Client.HttpException)
|
||||||
|
|
|
@ -100,9 +100,9 @@ hoistClient = hoistClientMonad (Proxy :: Proxy ClientM)
|
||||||
-- | @ClientM@ is the monad in which client functions run. Contains the
|
-- | @ClientM@ is the monad in which client functions run. Contains the
|
||||||
-- 'Client.Manager' and 'BaseUrl' used for requests in the reader environment.
|
-- 'Client.Manager' and 'BaseUrl' used for requests in the reader environment.
|
||||||
newtype ClientM a = ClientM
|
newtype ClientM a = ClientM
|
||||||
{ unClientM :: ReaderT ClientEnv (ExceptT ServantError (Codensity IO)) a }
|
{ unClientM :: ReaderT ClientEnv (ExceptT ClientError (Codensity IO)) a }
|
||||||
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
||||||
, MonadReader ClientEnv, MonadError ServantError)
|
, MonadReader ClientEnv, MonadError ClientError)
|
||||||
|
|
||||||
instance MonadBase IO ClientM where
|
instance MonadBase IO ClientM where
|
||||||
liftBase = ClientM . liftIO
|
liftBase = ClientM . liftIO
|
||||||
|
@ -113,12 +113,12 @@ instance Alt ClientM where
|
||||||
|
|
||||||
instance RunClient ClientM where
|
instance RunClient ClientM where
|
||||||
runRequest = performRequest
|
runRequest = performRequest
|
||||||
throwServantError = throwError
|
throwClientError = throwError
|
||||||
|
|
||||||
instance RunStreamingClient ClientM where
|
instance RunStreamingClient ClientM where
|
||||||
withStreamingRequest = performWithStreamingRequest
|
withStreamingRequest = performWithStreamingRequest
|
||||||
|
|
||||||
withClientM :: ClientM a -> ClientEnv -> (Either ServantError a -> IO b) -> IO b
|
withClientM :: ClientM a -> ClientEnv -> (Either ClientError a -> IO b) -> IO b
|
||||||
withClientM cm env k =
|
withClientM cm env k =
|
||||||
let Codensity f = runExceptT $ flip runReaderT env $ unClientM cm
|
let Codensity f = runExceptT $ flip runReaderT env $ unClientM cm
|
||||||
in f k
|
in f k
|
||||||
|
@ -133,7 +133,7 @@ withClientM cm env k =
|
||||||
-- /Note:/ we 'force' the result, so the likehood of accidentally leaking a
|
-- /Note:/ we 'force' the result, so the likehood of accidentally leaking a
|
||||||
-- connection is smaller. Use with care.
|
-- connection is smaller. Use with care.
|
||||||
--
|
--
|
||||||
runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ServantError a)
|
runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ClientError a)
|
||||||
runClientM cm env = withClientM cm env (evaluate . force)
|
runClientM cm env = withClientM cm env (evaluate . force)
|
||||||
|
|
||||||
performRequest :: Request -> ClientM Response
|
performRequest :: Request -> ClientM Response
|
||||||
|
|
|
@ -184,8 +184,8 @@ server = serve api (
|
||||||
:<|> return
|
:<|> return
|
||||||
:<|> (\ name -> case name of
|
:<|> (\ name -> case name of
|
||||||
Just "alice" -> return alice
|
Just "alice" -> return alice
|
||||||
Just n -> throwError $ ServantErr 400 (n ++ " not found") "" []
|
Just n -> throwError $ ServerError 400 (n ++ " not found") "" []
|
||||||
Nothing -> throwError $ ServantErr 400 "missing parameter" "" [])
|
Nothing -> throwError $ ServerError 400 "missing parameter" "" [])
|
||||||
:<|> (\ names -> return (zipWith Person names [0..]))
|
:<|> (\ names -> return (zipWith Person names [0..]))
|
||||||
:<|> return
|
:<|> return
|
||||||
:<|> (Tagged $ \ _request respond -> respond $ Wai.responseLBS HTTP.ok200 [] "rawSuccess")
|
:<|> (Tagged $ \ _request respond -> respond $ Wai.responseLBS HTTP.ok200 [] "rawSuccess")
|
||||||
|
@ -260,7 +260,7 @@ genAuthServer = serveWithContext genAuthAPI genAuthServerContext (const (return
|
||||||
manager' :: C.Manager
|
manager' :: C.Manager
|
||||||
manager' = unsafePerformIO $ C.newManager C.defaultManagerSettings
|
manager' = unsafePerformIO $ C.newManager C.defaultManagerSettings
|
||||||
|
|
||||||
runClient :: ClientM a -> BaseUrl -> IO (Either ServantError a)
|
runClient :: ClientM a -> BaseUrl -> IO (Either ClientError a)
|
||||||
runClient x baseUrl' = runClientM x (mkClientEnv manager' baseUrl')
|
runClient x baseUrl' = runClientM x (mkClientEnv manager' baseUrl')
|
||||||
|
|
||||||
sucessSpec :: Spec
|
sucessSpec :: Spec
|
||||||
|
@ -352,7 +352,7 @@ sucessSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
|
||||||
|
|
||||||
wrappedApiSpec :: Spec
|
wrappedApiSpec :: Spec
|
||||||
wrappedApiSpec = describe "error status codes" $ do
|
wrappedApiSpec = describe "error status codes" $ do
|
||||||
let serveW api = serve api $ throwError $ ServantErr 500 "error message" "" []
|
let serveW api = serve api $ throwError $ ServerError 500 "error message" "" []
|
||||||
context "are correctly handled by the client" $
|
context "are correctly handled by the client" $
|
||||||
let test :: (WrappedApi, String) -> Spec
|
let test :: (WrappedApi, String) -> Spec
|
||||||
test (WrappedApi api, desc) =
|
test (WrappedApi api, desc) =
|
||||||
|
@ -475,7 +475,7 @@ connectionErrorAPI :: Proxy ConnectionErrorAPI
|
||||||
connectionErrorAPI = Proxy
|
connectionErrorAPI = Proxy
|
||||||
|
|
||||||
connectionErrorSpec :: Spec
|
connectionErrorSpec :: Spec
|
||||||
connectionErrorSpec = describe "Servant.Client.ServantError" $
|
connectionErrorSpec = describe "Servant.Client.ClientError" $
|
||||||
it "correctly catches ConnectionErrors when the HTTP request can't go through" $ do
|
it "correctly catches ConnectionErrors when the HTTP request can't go through" $ do
|
||||||
let getInt = client connectionErrorAPI
|
let getInt = client connectionErrorAPI
|
||||||
let baseUrl' = BaseUrl Http "example.invalid" 80 ""
|
let baseUrl' = BaseUrl Http "example.invalid" 80 ""
|
||||||
|
|
|
@ -112,7 +112,7 @@ powerOfTwo = (2 ^)
|
||||||
manager' :: C.Manager
|
manager' :: C.Manager
|
||||||
manager' = unsafePerformIO $ C.newManager C.defaultManagerSettings
|
manager' = unsafePerformIO $ C.newManager C.defaultManagerSettings
|
||||||
|
|
||||||
withClient :: ClientM a -> BaseUrl -> (Either ServantError a -> IO r) -> IO r
|
withClient :: ClientM a -> BaseUrl -> (Either ClientError a -> IO r) -> IO r
|
||||||
withClient x baseUrl' = withClientM x (mkClientEnv manager' baseUrl')
|
withClient x baseUrl' = withClientM x (mkClientEnv manager' baseUrl')
|
||||||
|
|
||||||
testRunSourceIO :: SourceIO a
|
testRunSourceIO :: SourceIO a
|
||||||
|
|
|
@ -123,9 +123,9 @@ hoistClient = hoistClientMonad (Proxy :: Proxy ClientM)
|
||||||
-- | @ClientM@ is the monad in which client functions run. Contains the
|
-- | @ClientM@ is the monad in which client functions run. Contains the
|
||||||
-- 'Client.Manager' and 'BaseUrl' used for requests in the reader environment.
|
-- 'Client.Manager' and 'BaseUrl' used for requests in the reader environment.
|
||||||
newtype ClientM a = ClientM
|
newtype ClientM a = ClientM
|
||||||
{ unClientM :: ReaderT ClientEnv (ExceptT ServantError (Codensity IO)) a }
|
{ unClientM :: ReaderT ClientEnv (ExceptT ClientError (Codensity IO)) a }
|
||||||
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
deriving ( Functor, Applicative, Monad, MonadIO, Generic
|
||||||
, MonadReader ClientEnv, MonadError ServantError)
|
, MonadReader ClientEnv, MonadError ClientError)
|
||||||
|
|
||||||
instance MonadBase IO ClientM where
|
instance MonadBase IO ClientM where
|
||||||
liftBase = ClientM . liftIO
|
liftBase = ClientM . liftIO
|
||||||
|
@ -136,15 +136,15 @@ instance Alt ClientM where
|
||||||
|
|
||||||
instance RunClient ClientM where
|
instance RunClient ClientM where
|
||||||
runRequest = performRequest
|
runRequest = performRequest
|
||||||
throwServantError = throwError
|
throwClientError = throwError
|
||||||
|
|
||||||
instance RunStreamingClient ClientM where
|
instance RunStreamingClient ClientM where
|
||||||
withStreamingRequest = performWithStreamingRequest
|
withStreamingRequest = performWithStreamingRequest
|
||||||
|
|
||||||
runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ServantError a)
|
runClientM :: NFData a => ClientM a -> ClientEnv -> IO (Either ClientError a)
|
||||||
runClientM cm env = withClientM cm env (evaluate . force)
|
runClientM cm env = withClientM cm env (evaluate . force)
|
||||||
|
|
||||||
withClientM :: ClientM a -> ClientEnv -> (Either ServantError a -> IO b) -> IO b
|
withClientM :: ClientM a -> ClientEnv -> (Either ClientError a -> IO b) -> IO b
|
||||||
withClientM cm env k =
|
withClientM cm env k =
|
||||||
let Codensity f = runExceptT $ flip runReaderT env $ unClientM cm
|
let Codensity f = runExceptT $ flip runReaderT env $ unClientM cm
|
||||||
in f k
|
in f k
|
||||||
|
@ -181,7 +181,7 @@ performWithStreamingRequest req k = do
|
||||||
x <- k (clientResponseToResponse res' (fromInputStream body'))
|
x <- k (clientResponseToResponse res' (fromInputStream body'))
|
||||||
k1 x
|
k1 x
|
||||||
|
|
||||||
mkFailureResponse :: BaseUrl -> Request -> ResponseF BSL.ByteString -> ServantError
|
mkFailureResponse :: BaseUrl -> Request -> ResponseF BSL.ByteString -> ClientError
|
||||||
mkFailureResponse burl request =
|
mkFailureResponse burl request =
|
||||||
FailureResponse (bimap (const ()) f request)
|
FailureResponse (bimap (const ()) f request)
|
||||||
where
|
where
|
||||||
|
@ -233,7 +233,7 @@ requestToClientRequest burl r = (request, body)
|
||||||
Nothing -> (Client.emptyBody, Nothing)
|
Nothing -> (Client.emptyBody, Nothing)
|
||||||
Just (body', typ) -> (convertBody body', Just (hContentType, renderHeader typ))
|
Just (body', typ) -> (convertBody body', Just (hContentType, renderHeader typ))
|
||||||
|
|
||||||
catchConnectionError :: IO a -> IO (Either ServantError a)
|
catchConnectionError :: IO a -> IO (Either ClientError a)
|
||||||
catchConnectionError action =
|
catchConnectionError action =
|
||||||
catch (Right <$> action) $ \e ->
|
catch (Right <$> action) $ \e ->
|
||||||
pure . Left . ConnectionError $ SomeException (e :: IOException)
|
pure . Left . ConnectionError $ SomeException (e :: IOException)
|
||||||
|
|
|
@ -182,8 +182,8 @@ server = serve api (
|
||||||
:<|> return
|
:<|> return
|
||||||
:<|> (\ name -> case name of
|
:<|> (\ name -> case name of
|
||||||
Just "alice" -> return alice
|
Just "alice" -> return alice
|
||||||
Just n -> throwError $ ServantErr 400 (n ++ " not found") "" []
|
Just n -> throwError $ ServerError 400 (n ++ " not found") "" []
|
||||||
Nothing -> throwError $ ServantErr 400 "missing parameter" "" [])
|
Nothing -> throwError $ ServerError 400 "missing parameter" "" [])
|
||||||
:<|> (\ names -> return (zipWith Person names [0..]))
|
:<|> (\ names -> return (zipWith Person names [0..]))
|
||||||
:<|> return
|
:<|> return
|
||||||
:<|> (Tagged $ \ _request respond -> respond $ Wai.responseLBS HTTP.ok200 [] "rawSuccess")
|
:<|> (Tagged $ \ _request respond -> respond $ Wai.responseLBS HTTP.ok200 [] "rawSuccess")
|
||||||
|
@ -254,10 +254,10 @@ genAuthServerContext = genAuthHandler :. EmptyContext
|
||||||
genAuthServer :: Application
|
genAuthServer :: Application
|
||||||
genAuthServer = serveWithContext genAuthAPI genAuthServerContext (const (return alice))
|
genAuthServer = serveWithContext genAuthAPI genAuthServerContext (const (return alice))
|
||||||
|
|
||||||
runClient :: NFData a => ClientM a -> BaseUrl -> IO (Either ServantError a)
|
runClient :: NFData a => ClientM a -> BaseUrl -> IO (Either ClientError a)
|
||||||
runClient x burl = withClientEnvIO burl (runClientM x)
|
runClient x burl = withClientEnvIO burl (runClientM x)
|
||||||
|
|
||||||
runClientUnsafe :: ClientM a -> BaseUrl -> IO (Either ServantError a)
|
runClientUnsafe :: ClientM a -> BaseUrl -> IO (Either ClientError a)
|
||||||
runClientUnsafe x burl = withClientEnvIO burl (runClientMUnsafe x)
|
runClientUnsafe x burl = withClientEnvIO burl (runClientMUnsafe x)
|
||||||
where
|
where
|
||||||
runClientMUnsafe x env = withClientM x env return
|
runClientMUnsafe x env = withClientM x env return
|
||||||
|
@ -343,7 +343,7 @@ sucessSpec = beforeAll (startWaiApp server) $ afterAll endWaiApp $ do
|
||||||
|
|
||||||
wrappedApiSpec :: Spec
|
wrappedApiSpec :: Spec
|
||||||
wrappedApiSpec = describe "error status codes" $ do
|
wrappedApiSpec = describe "error status codes" $ do
|
||||||
let serveW api = serve api $ throwError $ ServantErr 500 "error message" "" []
|
let serveW api = serve api $ throwError $ ServerError 500 "error message" "" []
|
||||||
context "are correctly handled by the client" $
|
context "are correctly handled by the client" $
|
||||||
let test :: (WrappedApi, String) -> Spec
|
let test :: (WrappedApi, String) -> Spec
|
||||||
test (WrappedApi api, desc) =
|
test (WrappedApi api, desc) =
|
||||||
|
@ -467,7 +467,7 @@ connectionErrorAPI :: Proxy ConnectionErrorAPI
|
||||||
connectionErrorAPI = Proxy
|
connectionErrorAPI = Proxy
|
||||||
|
|
||||||
connectionErrorSpec :: Spec
|
connectionErrorSpec :: Spec
|
||||||
connectionErrorSpec = describe "Servant.Client.ServantError" $
|
connectionErrorSpec = describe "Servant.Client.ClientError" $
|
||||||
xit "correctly catches ConnectionErrors when the HTTP request can't go through" $ do
|
xit "correctly catches ConnectionErrors when the HTTP request can't go through" $ do
|
||||||
let getInt = client connectionErrorAPI
|
let getInt = client connectionErrorAPI
|
||||||
let baseUrl' = BaseUrl Http "example.invalid" 80 ""
|
let baseUrl' = BaseUrl Http "example.invalid" 80 ""
|
||||||
|
|
|
@ -84,7 +84,7 @@ server = serve api
|
||||||
powerOfTwo :: Int -> Int
|
powerOfTwo :: Int -> Int
|
||||||
powerOfTwo = (2 ^)
|
powerOfTwo = (2 ^)
|
||||||
|
|
||||||
withClient :: ClientM a -> BaseUrl -> (Either ServantError a -> IO r) -> IO r
|
withClient :: ClientM a -> BaseUrl -> (Either ClientError a -> IO r) -> IO r
|
||||||
withClient x burl k = do
|
withClient x burl k = do
|
||||||
withClientEnvIO burl $ \env -> withClientM x env k
|
withClientEnvIO burl $ \env -> withClientM x env k
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ library
|
||||||
Servant.Server.Internal.Handler
|
Servant.Server.Internal.Handler
|
||||||
Servant.Server.Internal.Router
|
Servant.Server.Internal.Router
|
||||||
Servant.Server.Internal.RoutingApplication
|
Servant.Server.Internal.RoutingApplication
|
||||||
Servant.Server.Internal.ServantErr
|
Servant.Server.Internal.ServerError
|
||||||
Servant.Server.StaticFiles
|
Servant.Server.StaticFiles
|
||||||
|
|
||||||
-- deprecated
|
-- deprecated
|
||||||
|
|
|
@ -49,7 +49,7 @@ module Servant.Server
|
||||||
-- , mkAuthHandler
|
-- , mkAuthHandler
|
||||||
|
|
||||||
-- * Default error type
|
-- * Default error type
|
||||||
, ServantErr(..)
|
, ServerError(..)
|
||||||
-- ** 3XX
|
-- ** 3XX
|
||||||
, err300
|
, err300
|
||||||
, err301
|
, err301
|
||||||
|
|
|
@ -25,7 +25,7 @@ module Servant.Server.Internal
|
||||||
, module Servant.Server.Internal.Handler
|
, module Servant.Server.Internal.Handler
|
||||||
, module Servant.Server.Internal.Router
|
, module Servant.Server.Internal.Router
|
||||||
, module Servant.Server.Internal.RoutingApplication
|
, module Servant.Server.Internal.RoutingApplication
|
||||||
, module Servant.Server.Internal.ServantErr
|
, module Servant.Server.Internal.ServerError
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
|
@ -91,7 +91,7 @@ import Servant.Server.Internal.Context
|
||||||
import Servant.Server.Internal.Handler
|
import Servant.Server.Internal.Handler
|
||||||
import Servant.Server.Internal.Router
|
import Servant.Server.Internal.Router
|
||||||
import Servant.Server.Internal.RoutingApplication
|
import Servant.Server.Internal.RoutingApplication
|
||||||
import Servant.Server.Internal.ServantErr
|
import Servant.Server.Internal.ServerError
|
||||||
|
|
||||||
#ifdef HAS_TYPE_ERROR
|
#ifdef HAS_TYPE_ERROR
|
||||||
import GHC.TypeLits
|
import GHC.TypeLits
|
||||||
|
|
|
@ -27,7 +27,7 @@ import Network.Wai
|
||||||
import Servant.API.BasicAuth
|
import Servant.API.BasicAuth
|
||||||
(BasicAuthData (BasicAuthData))
|
(BasicAuthData (BasicAuthData))
|
||||||
import Servant.Server.Internal.RoutingApplication
|
import Servant.Server.Internal.RoutingApplication
|
||||||
import Servant.Server.Internal.ServantErr
|
import Servant.Server.Internal.ServerError
|
||||||
|
|
||||||
-- * Basic Auth
|
-- * Basic Auth
|
||||||
|
|
||||||
|
|
|
@ -22,13 +22,13 @@ import Control.Monad.Trans.Except
|
||||||
(ExceptT, runExceptT)
|
(ExceptT, runExceptT)
|
||||||
import GHC.Generics
|
import GHC.Generics
|
||||||
(Generic)
|
(Generic)
|
||||||
import Servant.Server.Internal.ServantErr
|
import Servant.Server.Internal.ServerError
|
||||||
(ServantErr)
|
(ServerError)
|
||||||
|
|
||||||
newtype Handler a = Handler { runHandler' :: ExceptT ServantErr IO a }
|
newtype Handler a = Handler { runHandler' :: ExceptT ServerError IO a }
|
||||||
deriving
|
deriving
|
||||||
( Functor, Applicative, Monad, MonadIO, Generic
|
( Functor, Applicative, Monad, MonadIO, Generic
|
||||||
, MonadError ServantErr
|
, MonadError ServerError
|
||||||
, MonadThrow, MonadCatch, MonadMask
|
, MonadThrow, MonadCatch, MonadMask
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ instance MonadBase IO Handler where
|
||||||
liftBase = Handler . liftBase
|
liftBase = Handler . liftBase
|
||||||
|
|
||||||
instance MonadBaseControl IO Handler where
|
instance MonadBaseControl IO Handler where
|
||||||
type StM Handler a = Either ServantErr a
|
type StM Handler a = Either ServerError a
|
||||||
|
|
||||||
-- liftBaseWith :: (RunInBase Handler IO -> IO a) -> Handler a
|
-- liftBaseWith :: (RunInBase Handler IO -> IO a) -> Handler a
|
||||||
liftBaseWith f = Handler (liftBaseWith (\g -> f (g . runHandler')))
|
liftBaseWith f = Handler (liftBaseWith (\g -> f (g . runHandler')))
|
||||||
|
@ -44,5 +44,5 @@ instance MonadBaseControl IO Handler where
|
||||||
-- restoreM :: StM Handler a -> Handler a
|
-- restoreM :: StM Handler a -> Handler a
|
||||||
restoreM st = Handler (restoreM st)
|
restoreM st = Handler (restoreM st)
|
||||||
|
|
||||||
runHandler :: Handler a -> IO (Either ServantErr a)
|
runHandler :: Handler a -> IO (Either ServerError a)
|
||||||
runHandler = runExceptT . runHandler'
|
runHandler = runExceptT . runHandler'
|
||||||
|
|
|
@ -18,7 +18,7 @@ import qualified Data.Text as T
|
||||||
import Network.Wai
|
import Network.Wai
|
||||||
(Response, pathInfo)
|
(Response, pathInfo)
|
||||||
import Servant.Server.Internal.RoutingApplication
|
import Servant.Server.Internal.RoutingApplication
|
||||||
import Servant.Server.Internal.ServantErr
|
import Servant.Server.Internal.ServerError
|
||||||
|
|
||||||
type Router env = Router' env RoutingApplication
|
type Router env = Router' env RoutingApplication
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ import Network.Wai
|
||||||
import Prelude ()
|
import Prelude ()
|
||||||
import Prelude.Compat
|
import Prelude.Compat
|
||||||
import Servant.Server.Internal.Handler
|
import Servant.Server.Internal.Handler
|
||||||
import Servant.Server.Internal.ServantErr
|
import Servant.Server.Internal.ServerError
|
||||||
|
|
||||||
type RoutingApplication =
|
type RoutingApplication =
|
||||||
Request -- ^ the request, the field 'pathInfo' may be modified by url routing
|
Request -- ^ the request, the field 'pathInfo' may be modified by url routing
|
||||||
|
@ -39,9 +39,9 @@ type RoutingApplication =
|
||||||
|
|
||||||
-- | The result of matching against a path in the route tree.
|
-- | The result of matching against a path in the route tree.
|
||||||
data RouteResult a =
|
data RouteResult a =
|
||||||
Fail ServantErr -- ^ Keep trying other paths. The @ServantErr@
|
Fail ServerError -- ^ Keep trying other paths. The @ServantErr@
|
||||||
-- should only be 404, 405 or 406.
|
-- should only be 404, 405 or 406.
|
||||||
| FailFatal !ServantErr -- ^ Don't try other paths.
|
| FailFatal !ServerError -- ^ Don't try other paths.
|
||||||
| Route !a
|
| Route !a
|
||||||
deriving (Eq, Show, Read, Functor)
|
deriving (Eq, Show, Read, Functor)
|
||||||
|
|
||||||
|
@ -97,8 +97,8 @@ toApplication :: RoutingApplication -> Application
|
||||||
toApplication ra request respond = ra request routingRespond
|
toApplication ra request respond = ra request routingRespond
|
||||||
where
|
where
|
||||||
routingRespond :: RouteResult Response -> IO ResponseReceived
|
routingRespond :: RouteResult Response -> IO ResponseReceived
|
||||||
routingRespond (Fail err) = respond $ responseServantErr err
|
routingRespond (Fail err) = respond $ responseServerError err
|
||||||
routingRespond (FailFatal err) = respond $ responseServantErr err
|
routingRespond (FailFatal err) = respond $ responseServerError err
|
||||||
routingRespond (Route v) = respond v
|
routingRespond (Route v) = respond v
|
||||||
|
|
||||||
-- | A 'Delayed' is a representation of a handler with scheduled
|
-- | A 'Delayed' is a representation of a handler with scheduled
|
||||||
|
@ -235,11 +235,11 @@ emptyDelayed result =
|
||||||
r = return ()
|
r = return ()
|
||||||
|
|
||||||
-- | Fail with the option to recover.
|
-- | Fail with the option to recover.
|
||||||
delayedFail :: ServantErr -> DelayedIO a
|
delayedFail :: ServerError -> DelayedIO a
|
||||||
delayedFail err = liftRouteResult $ Fail err
|
delayedFail err = liftRouteResult $ Fail err
|
||||||
|
|
||||||
-- | Fail fatally, i.e., without any option to recover.
|
-- | Fail fatally, i.e., without any option to recover.
|
||||||
delayedFailFatal :: ServantErr -> DelayedIO a
|
delayedFailFatal :: ServerError -> DelayedIO a
|
||||||
delayedFailFatal err = liftRouteResult $ FailFatal err
|
delayedFailFatal err = liftRouteResult $ FailFatal err
|
||||||
|
|
||||||
-- | Gain access to the incoming request.
|
-- | Gain access to the incoming request.
|
||||||
|
@ -388,7 +388,7 @@ runAction action env req respond k = runResourceT $
|
||||||
go (Route a) = liftIO $ do
|
go (Route a) = liftIO $ do
|
||||||
e <- runHandler a
|
e <- runHandler a
|
||||||
case e of
|
case e of
|
||||||
Left err -> return . Route $ responseServantErr err
|
Left err -> return . Route $ responseServerError err
|
||||||
Right x -> return $! k x
|
Right x -> return $! k x
|
||||||
|
|
||||||
{- Note [Existential Record Update]
|
{- Note [Existential Record Update]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{-# LANGUAGE DeriveDataTypeable #-}
|
{-# LANGUAGE DeriveDataTypeable #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
module Servant.Server.Internal.ServantErr where
|
module Servant.Server.Internal.ServerError where
|
||||||
|
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
(Exception)
|
(Exception)
|
||||||
|
@ -13,16 +13,18 @@ import qualified Network.HTTP.Types as HTTP
|
||||||
import Network.Wai
|
import Network.Wai
|
||||||
(Response, responseLBS)
|
(Response, responseLBS)
|
||||||
|
|
||||||
data ServantErr = ServantErr { errHTTPCode :: Int
|
data ServerError = ServerError
|
||||||
, errReasonPhrase :: String
|
{ errHTTPCode :: Int
|
||||||
, errBody :: LBS.ByteString
|
, errReasonPhrase :: String
|
||||||
, errHeaders :: [HTTP.Header]
|
, errBody :: LBS.ByteString
|
||||||
} deriving (Show, Eq, Read, Typeable)
|
, errHeaders :: [HTTP.Header]
|
||||||
|
}
|
||||||
|
deriving (Show, Eq, Read, Typeable)
|
||||||
|
|
||||||
instance Exception ServantErr
|
instance Exception ServerError
|
||||||
|
|
||||||
responseServantErr :: ServantErr -> Response
|
responseServerError :: ServerError -> Response
|
||||||
responseServantErr ServantErr{..} = responseLBS status errHeaders errBody
|
responseServerError ServerError{..} = responseLBS status errHeaders errBody
|
||||||
where
|
where
|
||||||
status = HTTP.mkStatus errHTTPCode (BS.pack errReasonPhrase)
|
status = HTTP.mkStatus errHTTPCode (BS.pack errReasonPhrase)
|
||||||
|
|
||||||
|
@ -33,8 +35,8 @@ responseServantErr ServantErr{..} = responseLBS status errHeaders errBody
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err300 { errBody = "I can't choose." }
|
-- > failingHandler = throwError $ err300 { errBody = "I can't choose." }
|
||||||
--
|
--
|
||||||
err300 :: ServantErr
|
err300 :: ServerError
|
||||||
err300 = ServantErr { errHTTPCode = 300
|
err300 = ServerError { errHTTPCode = 300
|
||||||
, errReasonPhrase = "Multiple Choices"
|
, errReasonPhrase = "Multiple Choices"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -47,8 +49,8 @@ err300 = ServantErr { errHTTPCode = 300
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err301
|
-- > failingHandler = throwError err301
|
||||||
--
|
--
|
||||||
err301 :: ServantErr
|
err301 :: ServerError
|
||||||
err301 = ServantErr { errHTTPCode = 301
|
err301 = ServerError { errHTTPCode = 301
|
||||||
, errReasonPhrase = "Moved Permanently"
|
, errReasonPhrase = "Moved Permanently"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -61,8 +63,8 @@ err301 = ServantErr { errHTTPCode = 301
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err302
|
-- > failingHandler = throwError err302
|
||||||
--
|
--
|
||||||
err302 :: ServantErr
|
err302 :: ServerError
|
||||||
err302 = ServantErr { errHTTPCode = 302
|
err302 = ServerError { errHTTPCode = 302
|
||||||
, errReasonPhrase = "Found"
|
, errReasonPhrase = "Found"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -75,8 +77,8 @@ err302 = ServantErr { errHTTPCode = 302
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err303
|
-- > failingHandler = throwError err303
|
||||||
--
|
--
|
||||||
err303 :: ServantErr
|
err303 :: ServerError
|
||||||
err303 = ServantErr { errHTTPCode = 303
|
err303 = ServerError { errHTTPCode = 303
|
||||||
, errReasonPhrase = "See Other"
|
, errReasonPhrase = "See Other"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -89,8 +91,8 @@ err303 = ServantErr { errHTTPCode = 303
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err304
|
-- > failingHandler = throwError err304
|
||||||
--
|
--
|
||||||
err304 :: ServantErr
|
err304 :: ServerError
|
||||||
err304 = ServantErr { errHTTPCode = 304
|
err304 = ServerError { errHTTPCode = 304
|
||||||
, errReasonPhrase = "Not Modified"
|
, errReasonPhrase = "Not Modified"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -103,8 +105,8 @@ err304 = ServantErr { errHTTPCode = 304
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err305
|
-- > failingHandler = throwError err305
|
||||||
--
|
--
|
||||||
err305 :: ServantErr
|
err305 :: ServerError
|
||||||
err305 = ServantErr { errHTTPCode = 305
|
err305 = ServerError { errHTTPCode = 305
|
||||||
, errReasonPhrase = "Use Proxy"
|
, errReasonPhrase = "Use Proxy"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -117,8 +119,8 @@ err305 = ServantErr { errHTTPCode = 305
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err307
|
-- > failingHandler = throwError err307
|
||||||
--
|
--
|
||||||
err307 :: ServantErr
|
err307 :: ServerError
|
||||||
err307 = ServantErr { errHTTPCode = 307
|
err307 = ServerError { errHTTPCode = 307
|
||||||
, errReasonPhrase = "Temporary Redirect"
|
, errReasonPhrase = "Temporary Redirect"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -131,8 +133,8 @@ err307 = ServantErr { errHTTPCode = 307
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." }
|
-- > failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." }
|
||||||
--
|
--
|
||||||
err400 :: ServantErr
|
err400 :: ServerError
|
||||||
err400 = ServantErr { errHTTPCode = 400
|
err400 = ServerError { errHTTPCode = 400
|
||||||
, errReasonPhrase = "Bad Request"
|
, errReasonPhrase = "Bad Request"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -145,8 +147,8 @@ err400 = ServantErr { errHTTPCode = 400
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." }
|
-- > failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." }
|
||||||
--
|
--
|
||||||
err401 :: ServantErr
|
err401 :: ServerError
|
||||||
err401 = ServantErr { errHTTPCode = 401
|
err401 = ServerError { errHTTPCode = 401
|
||||||
, errReasonPhrase = "Unauthorized"
|
, errReasonPhrase = "Unauthorized"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -159,8 +161,8 @@ err401 = ServantErr { errHTTPCode = 401
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." }
|
-- > failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." }
|
||||||
--
|
--
|
||||||
err402 :: ServantErr
|
err402 :: ServerError
|
||||||
err402 = ServantErr { errHTTPCode = 402
|
err402 = ServerError { errHTTPCode = 402
|
||||||
, errReasonPhrase = "Payment Required"
|
, errReasonPhrase = "Payment Required"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -173,8 +175,8 @@ err402 = ServantErr { errHTTPCode = 402
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err403 { errBody = "Please login first." }
|
-- > failingHandler = throwError $ err403 { errBody = "Please login first." }
|
||||||
--
|
--
|
||||||
err403 :: ServantErr
|
err403 :: ServerError
|
||||||
err403 = ServantErr { errHTTPCode = 403
|
err403 = ServerError { errHTTPCode = 403
|
||||||
, errReasonPhrase = "Forbidden"
|
, errReasonPhrase = "Forbidden"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -187,8 +189,8 @@ err403 = ServantErr { errHTTPCode = 403
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
|
-- > failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
|
||||||
--
|
--
|
||||||
err404 :: ServantErr
|
err404 :: ServerError
|
||||||
err404 = ServantErr { errHTTPCode = 404
|
err404 = ServerError { errHTTPCode = 404
|
||||||
, errReasonPhrase = "Not Found"
|
, errReasonPhrase = "Not Found"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -201,8 +203,8 @@ err404 = ServantErr { errHTTPCode = 404
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
|
-- > failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
|
||||||
--
|
--
|
||||||
err405 :: ServantErr
|
err405 :: ServerError
|
||||||
err405 = ServantErr { errHTTPCode = 405
|
err405 = ServerError { errHTTPCode = 405
|
||||||
, errReasonPhrase = "Method Not Allowed"
|
, errReasonPhrase = "Method Not Allowed"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -215,8 +217,8 @@ err405 = ServantErr { errHTTPCode = 405
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err406
|
-- > failingHandler = throwError err406
|
||||||
--
|
--
|
||||||
err406 :: ServantErr
|
err406 :: ServerError
|
||||||
err406 = ServantErr { errHTTPCode = 406
|
err406 = ServerError { errHTTPCode = 406
|
||||||
, errReasonPhrase = "Not Acceptable"
|
, errReasonPhrase = "Not Acceptable"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -229,8 +231,8 @@ err406 = ServantErr { errHTTPCode = 406
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err407
|
-- > failingHandler = throwError err407
|
||||||
--
|
--
|
||||||
err407 :: ServantErr
|
err407 :: ServerError
|
||||||
err407 = ServantErr { errHTTPCode = 407
|
err407 = ServerError { errHTTPCode = 407
|
||||||
, errReasonPhrase = "Proxy Authentication Required"
|
, errReasonPhrase = "Proxy Authentication Required"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -243,8 +245,8 @@ err407 = ServantErr { errHTTPCode = 407
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
|
-- > failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
|
||||||
--
|
--
|
||||||
err409 :: ServantErr
|
err409 :: ServerError
|
||||||
err409 = ServantErr { errHTTPCode = 409
|
err409 = ServerError { errHTTPCode = 409
|
||||||
, errReasonPhrase = "Conflict"
|
, errReasonPhrase = "Conflict"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -257,8 +259,8 @@ err409 = ServantErr { errHTTPCode = 409
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
|
-- > failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
|
||||||
--
|
--
|
||||||
err410 :: ServantErr
|
err410 :: ServerError
|
||||||
err410 = ServantErr { errHTTPCode = 410
|
err410 = ServerError { errHTTPCode = 410
|
||||||
, errReasonPhrase = "Gone"
|
, errReasonPhrase = "Gone"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -271,8 +273,8 @@ err410 = ServantErr { errHTTPCode = 410
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError err411
|
-- > failingHandler = throwError err411
|
||||||
--
|
--
|
||||||
err411 :: ServantErr
|
err411 :: ServerError
|
||||||
err411 = ServantErr { errHTTPCode = 411
|
err411 = ServerError { errHTTPCode = 411
|
||||||
, errReasonPhrase = "Length Required"
|
, errReasonPhrase = "Length Required"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -285,8 +287,8 @@ err411 = ServantErr { errHTTPCode = 411
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
|
-- > failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
|
||||||
--
|
--
|
||||||
err412 :: ServantErr
|
err412 :: ServerError
|
||||||
err412 = ServantErr { errHTTPCode = 412
|
err412 = ServerError { errHTTPCode = 412
|
||||||
, errReasonPhrase = "Precondition Failed"
|
, errReasonPhrase = "Precondition Failed"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -299,8 +301,8 @@ err412 = ServantErr { errHTTPCode = 412
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." }
|
-- > failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." }
|
||||||
--
|
--
|
||||||
err413 :: ServantErr
|
err413 :: ServerError
|
||||||
err413 = ServantErr { errHTTPCode = 413
|
err413 = ServerError { errHTTPCode = 413
|
||||||
, errReasonPhrase = "Request Entity Too Large"
|
, errReasonPhrase = "Request Entity Too Large"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -313,8 +315,8 @@ err413 = ServantErr { errHTTPCode = 413
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err414 { errBody = "Maximum length is 64." }
|
-- > failingHandler = throwError $ err414 { errBody = "Maximum length is 64." }
|
||||||
--
|
--
|
||||||
err414 :: ServantErr
|
err414 :: ServerError
|
||||||
err414 = ServantErr { errHTTPCode = 414
|
err414 = ServerError { errHTTPCode = 414
|
||||||
, errReasonPhrase = "Request-URI Too Large"
|
, errReasonPhrase = "Request-URI Too Large"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -327,8 +329,8 @@ err414 = ServantErr { errHTTPCode = 414
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err415 { errBody = "Supported media types: gif, png" }
|
-- > failingHandler = throwError $ err415 { errBody = "Supported media types: gif, png" }
|
||||||
--
|
--
|
||||||
err415 :: ServantErr
|
err415 :: ServerError
|
||||||
err415 = ServantErr { errHTTPCode = 415
|
err415 = ServerError { errHTTPCode = 415
|
||||||
, errReasonPhrase = "Unsupported Media Type"
|
, errReasonPhrase = "Unsupported Media Type"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -341,8 +343,8 @@ err415 = ServantErr { errHTTPCode = 415
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." }
|
-- > failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." }
|
||||||
--
|
--
|
||||||
err416 :: ServantErr
|
err416 :: ServerError
|
||||||
err416 = ServantErr { errHTTPCode = 416
|
err416 = ServerError { errHTTPCode = 416
|
||||||
, errReasonPhrase = "Request range not satisfiable"
|
, errReasonPhrase = "Request range not satisfiable"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -355,8 +357,8 @@ err416 = ServantErr { errHTTPCode = 416
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
|
-- > failingHandler = throwError $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
|
||||||
--
|
--
|
||||||
err417 :: ServantErr
|
err417 :: ServerError
|
||||||
err417 = ServantErr { errHTTPCode = 417
|
err417 = ServerError { errHTTPCode = 417
|
||||||
, errReasonPhrase = "Expectation Failed"
|
, errReasonPhrase = "Expectation Failed"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -369,8 +371,8 @@ err417 = ServantErr { errHTTPCode = 417
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err418 { errBody = "Apologies, this is not a webserver but a teapot." }
|
-- > failingHandler = throwError $ err418 { errBody = "Apologies, this is not a webserver but a teapot." }
|
||||||
--
|
--
|
||||||
err418 :: ServantErr
|
err418 :: ServerError
|
||||||
err418 = ServantErr { errHTTPCode = 418
|
err418 = ServerError { errHTTPCode = 418
|
||||||
, errReasonPhrase = "I'm a teapot"
|
, errReasonPhrase = "I'm a teapot"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -383,8 +385,8 @@ err418 = ServantErr { errHTTPCode = 418
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err422 { errBody = "I understood your request, but can't process it." }
|
-- > failingHandler = throwError $ err422 { errBody = "I understood your request, but can't process it." }
|
||||||
--
|
--
|
||||||
err422 :: ServantErr
|
err422 :: ServerError
|
||||||
err422 = ServantErr { errHTTPCode = 422
|
err422 = ServerError { errHTTPCode = 422
|
||||||
, errReasonPhrase = "Unprocessable Entity"
|
, errReasonPhrase = "Unprocessable Entity"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -397,8 +399,8 @@ err422 = ServantErr { errHTTPCode = 422
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
|
-- > failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
|
||||||
--
|
--
|
||||||
err500 :: ServantErr
|
err500 :: ServerError
|
||||||
err500 = ServantErr { errHTTPCode = 500
|
err500 = ServerError { errHTTPCode = 500
|
||||||
, errReasonPhrase = "Internal Server Error"
|
, errReasonPhrase = "Internal Server Error"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -411,8 +413,8 @@ err500 = ServantErr { errHTTPCode = 500
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
|
-- > failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
|
||||||
--
|
--
|
||||||
err501 :: ServantErr
|
err501 :: ServerError
|
||||||
err501 = ServantErr { errHTTPCode = 501
|
err501 = ServerError { errHTTPCode = 501
|
||||||
, errReasonPhrase = "Not Implemented"
|
, errReasonPhrase = "Not Implemented"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -425,8 +427,8 @@ err501 = ServantErr { errHTTPCode = 501
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
|
-- > failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
|
||||||
--
|
--
|
||||||
err502 :: ServantErr
|
err502 :: ServerError
|
||||||
err502 = ServantErr { errHTTPCode = 502
|
err502 = ServerError { errHTTPCode = 502
|
||||||
, errReasonPhrase = "Bad Gateway"
|
, errReasonPhrase = "Bad Gateway"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -439,8 +441,8 @@ err502 = ServantErr { errHTTPCode = 502
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." }
|
-- > failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." }
|
||||||
--
|
--
|
||||||
err503 :: ServantErr
|
err503 :: ServerError
|
||||||
err503 = ServantErr { errHTTPCode = 503
|
err503 = ServerError { errHTTPCode = 503
|
||||||
, errReasonPhrase = "Service Unavailable"
|
, errReasonPhrase = "Service Unavailable"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -453,8 +455,8 @@ err503 = ServantErr { errHTTPCode = 503
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
|
-- > failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
|
||||||
--
|
--
|
||||||
err504 :: ServantErr
|
err504 :: ServerError
|
||||||
err504 = ServantErr { errHTTPCode = 504
|
err504 = ServerError { errHTTPCode = 504
|
||||||
, errReasonPhrase = "Gateway Time-out"
|
, errReasonPhrase = "Gateway Time-out"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
||||||
|
@ -467,8 +469,8 @@ err504 = ServantErr { errHTTPCode = 504
|
||||||
-- > failingHandler :: Handler ()
|
-- > failingHandler :: Handler ()
|
||||||
-- > failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." }
|
-- > failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." }
|
||||||
--
|
--
|
||||||
err505 :: ServantErr
|
err505 :: ServerError
|
||||||
err505 = ServantErr { errHTTPCode = 505
|
err505 = ServerError { errHTTPCode = 505
|
||||||
, errReasonPhrase = "HTTP Version not supported"
|
, errReasonPhrase = "HTTP Version not supported"
|
||||||
, errBody = ""
|
, errBody = ""
|
||||||
, errHeaders = []
|
, errHeaders = []
|
Loading…
Reference in a new issue