-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A family of combinators for defining webservices APIs and serving them -- -- A family of combinators for defining webservices APIs and serving them -- -- You can learn about the basics in the tutorial. -- -- Here is a runnable example, with comments, that defines a dummy -- API and implements a webserver that serves this API, using this -- package. -- -- CHANGELOG @package servant-server @version 0.16.2 module Servant.Server.Internal.Context -- | Contexts are used to pass values to combinators. (They are -- not meant to be used to pass parameters to your handlers, i.e. -- they should not replace any custom ReaderT-monad-stack that -- you're using with hoistServer.) If you don't use combinators -- that require any context entries, you can just use serve as -- always. -- -- If you are using combinators that require a non-empty Context -- you have to use serveWithContext and pass it a Context -- that contains all the values your combinators need. A Context -- is essentially a heterogenous list and accessing the elements is being -- done by type (see getContextEntry). The parameter of the type -- Context is a type-level list reflecting the types of the -- contained context entries. To create a Context with entries, -- use the operator (:.): -- --
-- >>> :type True :. () :. EmptyContext -- True :. () :. EmptyContext :: Context '[Bool, ()] --data Context contextTypes [EmptyContext] :: Context '[] [:.] :: x -> Context xs -> Context (x : xs) infixr 5 :. -- | This class is used to access context entries in Contexts. -- getContextEntry returns the first value where the type matches: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: Bool -- True ---- -- If the Context does not contain an entry of the requested type, -- you'll get an error: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: String -- ... -- ...No instance for (HasContextEntry '[] [Char]) -- ... --class HasContextEntry (context :: [*]) (val :: *) getContextEntry :: HasContextEntry context val => Context context -> val -- | Normally context entries are accessed by their types. In case you need -- to have multiple values of the same type in your Context and -- need to access them, we provide NamedContext. You can think of -- it as sub-namespaces for Contexts. data NamedContext (name :: Symbol) (subContext :: [*]) NamedContext :: Context subContext -> NamedContext -- | descendIntoNamedContext allows you to access -- NamedContexts. Usually you won't have to use it yourself but -- instead use a combinator like WithNamedContext. -- -- This is how descendIntoNamedContext works: -- --
-- >>> :set -XFlexibleContexts -- -- >>> let subContext = True :. EmptyContext -- -- >>> :type subContext -- subContext :: Context '[Bool] -- -- >>> let parentContext = False :. (NamedContext subContext :: NamedContext "subContext" '[Bool]) :. EmptyContext -- -- >>> :type parentContext -- parentContext :: Context '[Bool, NamedContext "subContext" '[Bool]] -- -- >>> descendIntoNamedContext (Proxy :: Proxy "subContext") parentContext :: Context '[Bool] -- True :. EmptyContext --descendIntoNamedContext :: forall context name subContext. HasContextEntry context (NamedContext name subContext) => Proxy (name :: Symbol) -> Context context -> Context subContext instance Servant.Server.Internal.Context.HasContextEntry xs val => Servant.Server.Internal.Context.HasContextEntry (notIt : xs) val instance Servant.Server.Internal.Context.HasContextEntry (val : xs) val instance GHC.Show.Show (Servant.Server.Internal.Context.Context '[]) instance (GHC.Show.Show a, GHC.Show.Show (Servant.Server.Internal.Context.Context as)) => GHC.Show.Show (Servant.Server.Internal.Context.Context (a : as)) instance GHC.Classes.Eq (Servant.Server.Internal.Context.Context '[]) instance (GHC.Classes.Eq a, GHC.Classes.Eq (Servant.Server.Internal.Context.Context as)) => GHC.Classes.Eq (Servant.Server.Internal.Context.Context (a : as)) module Servant.Server.Internal.ServerError data ServerError ServerError :: Int -> String -> ByteString -> [Header] -> ServerError [errHTTPCode] :: ServerError -> Int [errReasonPhrase] :: ServerError -> String [errBody] :: ServerError -> ByteString [errHeaders] :: ServerError -> [Header] responseServerError :: ServerError -> Response -- | err300 Multiple Choices -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err300 { errBody = "I can't choose." }
--
err300 :: ServerError
-- | err301 Moved Permanently
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err301 --err301 :: ServerError -- | err302 Found -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err302 --err302 :: ServerError -- | err303 See Other -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err303 --err303 :: ServerError -- | err304 Not Modified -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err304 --err304 :: ServerError -- | err305 Use Proxy -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err305 --err305 :: ServerError -- | err307 Temporary Redirect -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err307 --err307 :: ServerError -- | err400 Bad Request -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." }
--
err400 :: ServerError
-- | err401 Unauthorized
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." }
--
err401 :: ServerError
-- | err402 Payment Required
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." }
--
err402 :: ServerError
-- | err403 Forbidden
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err403 { errBody = "Please login first." }
--
err403 :: ServerError
-- | err404 Not Found
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
--
err404 :: ServerError
-- | err405 Method Not Allowed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
--
err405 :: ServerError
-- | err406 Not Acceptable
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err406 --err406 :: ServerError -- | err407 Proxy Authentication Required -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err407 --err407 :: ServerError -- | err409 Conflict -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
--
err409 :: ServerError
-- | err410 Gone
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
--
err410 :: ServerError
-- | err411 Length Required
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err411 --err411 :: ServerError -- | err412 Precondition Failed -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
--
err412 :: ServerError
-- | err413 Request Entity Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." }
--
err413 :: ServerError
-- | err414 Request-URI Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err414 { errBody = "Maximum length is 64." }
--
err414 :: ServerError
-- | err415 Unsupported Media Type
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err415 { errBody = "Supported media types: gif, png" }
--
err415 :: ServerError
-- | err416 Request range not satisfiable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." }
--
err416 :: ServerError
-- | err417 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
--
err417 :: ServerError
-- | err418 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err418 { errBody = "Apologies, this is not a webserver but a teapot." }
--
err418 :: ServerError
-- | err422 Unprocessable Entity
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err422 { errBody = "I understood your request, but can't process it." }
--
err422 :: ServerError
-- | err500 Internal Server Error
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
--
err500 :: ServerError
-- | err501 Not Implemented
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
--
err501 :: ServerError
-- | err502 Bad Gateway
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
--
err502 :: ServerError
-- | err503 Service Unavailable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." }
--
err503 :: ServerError
-- | err504 Gateway Time-out
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
--
err504 :: ServerError
-- | err505 HTTP Version not supported
--
-- Example usage:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." }
--
err505 :: ServerError
instance GHC.Read.Read Servant.Server.Internal.ServerError.ServerError
instance GHC.Classes.Eq Servant.Server.Internal.ServerError.ServerError
instance GHC.Show.Show Servant.Server.Internal.ServerError.ServerError
instance GHC.Exception.Type.Exception Servant.Server.Internal.ServerError.ServerError
module Servant.Server.Internal.RouteResult
-- | The result of matching against a path in the route tree.
data RouteResult a
-- | Keep trying other paths. The ServantError should only be 404,
-- 405 or 406.
Fail :: ServerError -> RouteResult a
-- | Don't try other paths.
FailFatal :: !ServerError -> RouteResult a
Route :: !a -> RouteResult a
newtype RouteResultT m a
RouteResultT :: m (RouteResult a) -> RouteResultT m a
[runRouteResultT] :: RouteResultT m a -> m (RouteResult a)
instance GHC.Base.Functor m => GHC.Base.Functor (Servant.Server.Internal.RouteResult.RouteResultT m)
instance GHC.Base.Functor Servant.Server.Internal.RouteResult.RouteResult
instance GHC.Read.Read a => GHC.Read.Read (Servant.Server.Internal.RouteResult.RouteResult a)
instance GHC.Show.Show a => GHC.Show.Show (Servant.Server.Internal.RouteResult.RouteResult a)
instance GHC.Classes.Eq a => GHC.Classes.Eq (Servant.Server.Internal.RouteResult.RouteResult a)
instance Control.Monad.Trans.Class.MonadTrans Servant.Server.Internal.RouteResult.RouteResultT
instance (GHC.Base.Functor m, GHC.Base.Monad m) => GHC.Base.Applicative (Servant.Server.Internal.RouteResult.RouteResultT m)
instance GHC.Base.Monad m => GHC.Base.Monad (Servant.Server.Internal.RouteResult.RouteResultT m)
instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Servant.Server.Internal.RouteResult.RouteResultT m)
instance Control.Monad.Base.MonadBase b m => Control.Monad.Base.MonadBase b (Servant.Server.Internal.RouteResult.RouteResultT m)
instance Control.Monad.Trans.Control.MonadBaseControl b m => Control.Monad.Trans.Control.MonadBaseControl b (Servant.Server.Internal.RouteResult.RouteResultT m)
instance Control.Monad.Trans.Control.MonadTransControl Servant.Server.Internal.RouteResult.RouteResultT
instance Control.Monad.Catch.MonadThrow m => Control.Monad.Catch.MonadThrow (Servant.Server.Internal.RouteResult.RouteResultT m)
instance GHC.Base.Applicative Servant.Server.Internal.RouteResult.RouteResult
instance GHC.Base.Monad Servant.Server.Internal.RouteResult.RouteResult
module Servant.Server.Internal.RoutingApplication
type RoutingApplication = Request " the request, the field 'pathInfo' may be modified by url routing" -> (RouteResult Response -> IO ResponseReceived) -> IO ResponseReceived
toApplication :: RoutingApplication -> Application
module Servant.Server.Internal.Router
type Router env = Router' env RoutingApplication
-- | Internal representation of a router.
--
-- The first argument describes an environment type that is expected as
-- extra input by the routers at the leaves. The environment is filled
-- while running the router, with path components that can be used to
-- process captures.
data Router' env a
-- | the map contains routers for subpaths (first path component used for
-- lookup and removed afterwards), the list contains handlers for the
-- empty path, to be tried in order
StaticRouter :: Map Text (Router' env a) -> [env -> a] -> Router' env a
-- | first path component is passed to the child router in its environment
-- and removed afterwards
CaptureRouter :: Router' (Text, env) a -> Router' env a
-- | all path components are passed to the child router in its environment
-- and are removed afterwards
CaptureAllRouter :: Router' ([Text], env) a -> Router' env a
-- | to be used for routes we do not know anything about
RawRouter :: (env -> a) -> Router' env a
-- | left-biased choice between two routers
Choice :: Router' env a -> Router' env a -> Router' env a
-- | Smart constructor for a single static path component.
pathRouter :: Text -> Router' env a -> Router' env a
-- | Smart constructor for a leaf, i.e., a router that expects the empty
-- path.
leafRouter :: (env -> a) -> Router' env a
-- | Smart constructor for the choice between routers. We currently
-- optimize the following cases:
--
-- -- 404 -- 405 (bad method) -- 401 (unauthorized) -- 415 (unsupported media type) -- 406 (not acceptable) -- 400 (bad request) ---- -- Therefore, while routing, we delay most checks so that they will -- ultimately occur in the right order. -- -- A Delayed contains many delayed blocks of tests, and the actual -- handler: -- --
-- type MyApi = "books" :> Get '[JSON] [Book] -- GET /books -- :<|> "books" :> ReqBody Book :> Post '[JSON] Book -- POST /books -- -- server :: Server MyApi -- server = listAllBooks :<|> postBook -- where listAllBooks = ... -- postBook book = ... -- -- myApi :: Proxy MyApi -- myApi = Proxy -- -- app :: Application -- app = serve myApi server -- -- main :: IO () -- main = Network.Wai.Handler.Warp.run 8080 app --serve :: HasServer api '[] => Proxy api -> Server api -> Application serveWithContext :: HasServer api context => Proxy api -> Context context -> Server api -> Application toApplication :: RoutingApplication -> Application class HasServer api context where { type family ServerT api (m :: * -> *) :: *; } route :: HasServer api context => Proxy api -> Context context -> Delayed env (Server api) -> Router env hoistServerWithContext :: HasServer api context => Proxy api -> Proxy context -> (forall x. m x -> n x) -> ServerT api m -> ServerT api n type Server api = ServerT api Handler -- | Singleton type representing a server that serves an empty API. data EmptyServer -- | Server for EmptyAPI emptyServer :: ServerT EmptyAPI m newtype Handler a Handler :: ExceptT ServerError IO a -> Handler a [runHandler'] :: Handler a -> ExceptT ServerError IO a runHandler :: Handler a -> IO (Either ServerError a) -- | The function layout produces a textual description of the -- internal router layout for debugging purposes. Note that the router -- layout is determined just by the API, not by the handlers. -- -- Example: -- -- For the following API -- --
-- type API = -- "a" :> "d" :> Get '[JSON] NoContent -- :<|> "b" :> Capture "x" Int :> Get '[JSON] Bool -- :<|> "c" :> Put '[JSON] Bool -- :<|> "a" :> "e" :> Get '[JSON] Int -- :<|> "b" :> Capture "x" Int :> Put '[JSON] Bool -- :<|> Raw ---- -- we get the following output: -- --
-- / -- ├─ a/ -- │ ├─ d/ -- │ │ └─• -- │ └─ e/ -- │ └─• -- ├─ b/ -- │ └─ <capture>/ -- │ ├─• -- │ ┆ -- │ └─• -- ├─ c/ -- │ └─• -- ┆ -- └─ <raw> ---- -- Explanation of symbols: -- --
-- >>> import Control.Monad.Reader -- -- >>> type ReaderAPI = "ep1" :> Get '[JSON] Int :<|> "ep2" :> Get '[JSON] String :<|> Raw :<|> EmptyAPI -- -- >>> let readerApi = Proxy :: Proxy ReaderAPI -- -- >>> let readerServer = return 1797 :<|> ask :<|> Tagged (error "raw server") :<|> emptyServer :: ServerT ReaderAPI (Reader String) -- -- >>> let nt x = return (runReader x "hi") -- -- >>> let mainServer = hoistServer readerApi nt readerServer :: Server ReaderAPI --hoistServer :: HasServer api '[] => Proxy api -> (forall x. m x -> n x) -> ServerT api m -> ServerT api n -- | Apply a transformation to the response of a Router. tweakResponse :: (RouteResult Response -> RouteResult Response) -> Router env -> Router env -- | Contexts are used to pass values to combinators. (They are -- not meant to be used to pass parameters to your handlers, i.e. -- they should not replace any custom ReaderT-monad-stack that -- you're using with hoistServer.) If you don't use combinators -- that require any context entries, you can just use serve as -- always. -- -- If you are using combinators that require a non-empty Context -- you have to use serveWithContext and pass it a Context -- that contains all the values your combinators need. A Context -- is essentially a heterogenous list and accessing the elements is being -- done by type (see getContextEntry). The parameter of the type -- Context is a type-level list reflecting the types of the -- contained context entries. To create a Context with entries, -- use the operator (:.): -- --
-- >>> :type True :. () :. EmptyContext -- True :. () :. EmptyContext :: Context '[Bool, ()] --data Context contextTypes [EmptyContext] :: Context '[] [:.] :: x -> Context xs -> Context (x : xs) infixr 5 :. -- | This class is used to access context entries in Contexts. -- getContextEntry returns the first value where the type matches: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: Bool -- True ---- -- If the Context does not contain an entry of the requested type, -- you'll get an error: -- --
-- >>> getContextEntry (True :. False :. EmptyContext) :: String -- ... -- ...No instance for (HasContextEntry '[] [Char]) -- ... --class HasContextEntry (context :: [*]) (val :: *) getContextEntry :: HasContextEntry context val => Context context -> val -- | Normally context entries are accessed by their types. In case you need -- to have multiple values of the same type in your Context and -- need to access them, we provide NamedContext. You can think of -- it as sub-namespaces for Contexts. data NamedContext (name :: Symbol) (subContext :: [*]) NamedContext :: Context subContext -> NamedContext -- | descendIntoNamedContext allows you to access -- NamedContexts. Usually you won't have to use it yourself but -- instead use a combinator like WithNamedContext. -- -- This is how descendIntoNamedContext works: -- --
-- >>> :set -XFlexibleContexts -- -- >>> let subContext = True :. EmptyContext -- -- >>> :type subContext -- subContext :: Context '[Bool] -- -- >>> let parentContext = False :. (NamedContext subContext :: NamedContext "subContext" '[Bool]) :. EmptyContext -- -- >>> :type parentContext -- parentContext :: Context '[Bool, NamedContext "subContext" '[Bool]] -- -- >>> descendIntoNamedContext (Proxy :: Proxy "subContext") parentContext :: Context '[Bool] -- True :. EmptyContext --descendIntoNamedContext :: forall context name subContext. HasContextEntry context (NamedContext name subContext) => Proxy (name :: Symbol) -> Context context -> Context subContext -- | Datatype wrapping a function used to check authentication. newtype BasicAuthCheck usr BasicAuthCheck :: (BasicAuthData -> IO (BasicAuthResult usr)) -> BasicAuthCheck usr [unBasicAuthCheck] :: BasicAuthCheck usr -> BasicAuthData -> IO (BasicAuthResult usr) -- | servant-server's current implementation of basic authentication is not -- immune to certian kinds of timing attacks. Decoding payloads does not -- take a fixed amount of time. -- -- The result of authentication/authorization data BasicAuthResult usr Unauthorized :: BasicAuthResult usr BadPassword :: BasicAuthResult usr NoSuchUser :: BasicAuthResult usr Authorized :: usr -> BasicAuthResult usr data ServerError ServerError :: Int -> String -> ByteString -> [Header] -> ServerError [errHTTPCode] :: ServerError -> Int [errReasonPhrase] :: ServerError -> String [errBody] :: ServerError -> ByteString [errHeaders] :: ServerError -> [Header] -- | err300 Multiple Choices -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err300 { errBody = "I can't choose." }
--
err300 :: ServerError
-- | err301 Moved Permanently
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err301 --err301 :: ServerError -- | err302 Found -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err302 --err302 :: ServerError -- | err303 See Other -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err303 --err303 :: ServerError -- | err304 Not Modified -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err304 --err304 :: ServerError -- | err305 Use Proxy -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err305 --err305 :: ServerError -- | err307 Temporary Redirect -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err307 --err307 :: ServerError -- | err400 Bad Request -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err400 { errBody = "Your request makes no sense to me." }
--
err400 :: ServerError
-- | err401 Unauthorized
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err401 { errBody = "Your credentials are invalid." }
--
err401 :: ServerError
-- | err402 Payment Required
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err402 { errBody = "You have 0 credits. Please give me $$$." }
--
err402 :: ServerError
-- | err403 Forbidden
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err403 { errBody = "Please login first." }
--
err403 :: ServerError
-- | err404 Not Found
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
--
err404 :: ServerError
-- | err405 Method Not Allowed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
--
err405 :: ServerError
-- | err406 Not Acceptable
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err406 --err406 :: ServerError -- | err407 Proxy Authentication Required -- -- Example: -- --
-- failingHandler :: Handler () -- failingHandler = throwError err407 --err407 :: ServerError -- | err409 Conflict -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
--
err409 :: ServerError
-- | err410 Gone
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
--
err410 :: ServerError
-- | err411 Length Required
--
-- Example:
--
-- -- failingHandler :: Handler () -- failingHandler = throwError err411 --err411 :: ServerError -- | err412 Precondition Failed -- -- Example: -- --
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
--
err412 :: ServerError
-- | err413 Request Entity Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err413 { errBody = "Request exceeded 64k." }
--
err413 :: ServerError
-- | err414 Request-URI Too Large
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err414 { errBody = "Maximum length is 64." }
--
err414 :: ServerError
-- | err415 Unsupported Media Type
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err415 { errBody = "Supported media types: gif, png" }
--
err415 :: ServerError
-- | err416 Request range not satisfiable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err416 { errBody = "Valid range is [0, 424242]." }
--
err416 :: ServerError
-- | err417 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
--
err417 :: ServerError
-- | err418 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err418 { errBody = "Apologies, this is not a webserver but a teapot." }
--
err418 :: ServerError
-- | err422 Unprocessable Entity
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err422 { errBody = "I understood your request, but can't process it." }
--
err422 :: ServerError
-- | err500 Internal Server Error
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
--
err500 :: ServerError
-- | err501 Not Implemented
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
--
err501 :: ServerError
-- | err502 Bad Gateway
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
--
err502 :: ServerError
-- | err503 Service Unavailable
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err503 { errBody = "We're rewriting in PHP." }
--
err503 :: ServerError
-- | err504 Gateway Time-out
--
-- Example:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
--
err504 :: ServerError
-- | err505 HTTP Version not supported
--
-- Example usage:
--
--
-- failingHandler :: Handler ()
-- failingHandler = throwError $ err505 { errBody = "I support HTTP/4.0 only." }
--
err505 :: ServerError
-- | The WAI application.
--
-- Note that, since WAI 3.0, this type is structured in continuation
-- passing style to allow for proper safe resource handling. This was
-- handled in the past via other means (e.g., ResourceT). As a
-- demonstration:
--
-- -- app :: Application -- app req respond = bracket_ -- (putStrLn "Allocating scarce resource") -- (putStrLn "Cleaning up") -- (respond $ responseLBS status200 [] "Hello World") --type Application = Request -> Response -> IO ResponseReceived -> IO ResponseReceived -- | A Tagged s b value is a value b with an -- attached phantom type s. This can be used in place of the -- more traditional but less safe idiom of passing in an undefined value -- with the type, because unlike an (s -> b), a -- Tagged s b can't try to use the argument s as -- a real value. -- -- Moreover, you don't have to rely on the compiler to inline away the -- extra argument, because the newtype is "free" -- -- Tagged has kind k -> * -> * if the compiler -- supports PolyKinds, therefore there is an extra k -- showing in the instance haddocks that may cause confusion. newtype Tagged (s :: k) b :: forall k. () => k -> Type -> Type Tagged :: b -> Tagged b [unTagged] :: Tagged b -> b module Servant.Server.Generic -- | A type that specifies that an API record contains a server -- implementation. data AsServerT (m :: * -> *) type AsServer = AsServerT Handler -- | Transform record of routes into a WAI Application. genericServe :: forall routes. (HasServer (ToServantApi routes) '[], GenericServant routes AsServer, Server (ToServantApi routes) ~ ToServant routes AsServer) => routes AsServer -> Application -- | Transform a record of routes with custom monad into a WAI -- Application, by providing a transformation to bring each -- handler back in the Handler monad. genericServeT :: forall (routes :: * -> *) (m :: * -> *). (GenericServant routes (AsServerT m), GenericServant routes AsApi, HasServer (ToServantApi routes) '[], ServerT (ToServantApi routes) m ~ ToServant routes (AsServerT m)) => (forall a. m a -> Handler a) -> routes (AsServerT m) -> Application -- | Transform a record of routes with custom monad into a WAI -- Application, while using the given Context to serve the -- application (contexts are typically used by auth-related combinators -- in servant, e.g to hold auth checks) and the given transformation to -- map all the handlers back to the Handler monad. genericServeTWithContext :: forall (routes :: * -> *) (m :: * -> *) (ctx :: [*]). (GenericServant routes (AsServerT m), GenericServant routes AsApi, HasServer (ToServantApi routes) ctx, ServerT (ToServantApi routes) m ~ ToServant routes (AsServerT m)) => (forall a. m a -> Handler a) -> routes (AsServerT m) -> Context ctx -> Application -- | Transform record of endpoints into a Server. genericServer :: GenericServant routes AsServer => routes AsServer -> ToServant routes AsServer genericServerT :: GenericServant routes (AsServerT m) => routes (AsServerT m) -> ToServant routes (AsServerT m) instance Servant.API.Generic.GenericMode (Servant.Server.Generic.AsServerT m) -- | This module defines server-side handlers that lets you serve static -- files. -- -- The most common needs for a web application are covered by -- serveDirectoryWebApp, but the other variants allow you to use -- different StaticSettings and serveDirectoryWith even -- allows you to specify arbitrary StaticSettings to be used for -- serving static files. module Servant.Server.StaticFiles -- | Serve anything under the specified directory as a Raw endpoint. -- --
-- type MyApi = "static" :> Raw -- -- server :: Server MyApi -- server = serveDirectoryWebApp "/var/www" ---- -- would capture any request to /static/<something> and -- look for <something> under /var/www. -- -- It will do its best to guess the MIME type for that file, based on the -- extension, and send an appropriate Content-Type header if -- possible. -- -- If your goal is to serve HTML, CSS and Javascript files that use the -- rest of the API as a webapp backend, you will most likely not want the -- static files to be hidden behind a /static/ prefix. In that -- case, remember to put the serveDirectoryWebApp handler in the -- last position, because servant will try to match the handlers -- in order. -- -- Corresponds to the defaultWebAppSettings StaticSettings -- value. serveDirectoryWebApp :: FilePath -> ServerT Raw m -- | Same as serveDirectoryWebApp, but uses -- webAppSettingsWithLookup. serveDirectoryWebAppLookup :: ETagLookup -> FilePath -> ServerT Raw m -- | Same as serveDirectoryWebApp, but uses -- defaultFileServerSettings. serveDirectoryFileServer :: FilePath -> ServerT Raw m -- | Uses embeddedSettings. serveDirectoryEmbedded :: [(FilePath, ByteString)] -> ServerT Raw m -- | Alias for staticApp. Lets you serve a directory with arbitrary -- StaticSettings. Useful when you want particular settings not -- covered by the four other variants. This is the most flexible method. serveDirectoryWith :: StaticSettings -> ServerT Raw m -- | Same as serveDirectoryFileServer. It used to be the only file -- serving function in servant pre-0.10 and will be kept around for a few -- versions, but is deprecated. -- | Deprecated: Use serveDirectoryFileServer instead serveDirectory :: FilePath -> ServerT Raw m module Servant -- | Proxy is a type that holds no data, but has a phantom parameter -- of arbitrary type (or even kind). Its use is to provide type -- information, even though there is no value available of that type (or -- it may be too costly to create one). -- -- Historically, Proxy :: Proxy a is a safer -- alternative to the 'undefined :: a' idiom. -- --
-- >>> Proxy :: Proxy (Void, Int -> Int) -- Proxy ---- -- Proxy can even hold types of higher kinds, -- --
-- >>> Proxy :: Proxy Either -- Proxy ---- --
-- >>> Proxy :: Proxy Functor -- Proxy ---- --
-- >>> Proxy :: Proxy complicatedStructure -- Proxy --data Proxy (t :: k) :: forall k. () => k -> Type Proxy :: Proxy -- | Is used within a monadic computation to begin exception processing. throwError :: MonadError e m => e -> m a module Servant.Server.Experimental.Auth -- | Specify the type of data returned after we've authenticated a request. -- quite often this is some User datatype. -- -- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE type family AuthServerData a :: * -- | Handlers for AuthProtected resources -- -- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE newtype AuthHandler r usr AuthHandler :: (r -> Handler usr) -> AuthHandler r usr [unAuthHandler] :: AuthHandler r usr -> r -> Handler usr -- | NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE mkAuthHandler :: (r -> Handler usr) -> AuthHandler r usr instance GHC.Generics.Generic (Servant.Server.Experimental.Auth.AuthHandler r usr) instance forall k api (context :: [*]) (tag :: k). (Servant.Server.Internal.HasServer api context, Servant.Server.Internal.Context.HasContextEntry context (Servant.Server.Experimental.Auth.AuthHandler Network.Wai.Internal.Request (Servant.Server.Experimental.Auth.AuthServerData (Servant.API.Experimental.Auth.AuthProtect tag)))) => Servant.Server.Internal.HasServer (Servant.API.Experimental.Auth.AuthProtect tag Servant.API.Sub.:> api) context -- | Deprecated: Use Servant.Server.StaticFiles. module Servant.Utils.StaticFiles