-- 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.6 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 enter.) 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) -- | 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 :: HasContextEntry context (NamedContext name subContext) => Proxy (name :: Symbol) -> Context context -> Context subContext 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)) 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 module Servant.Server.Internal.ServantErr data ServantErr ServantErr :: Int -> String -> ByteString -> [Header] -> ServantErr [errHTTPCode] :: ServantErr -> Int [errReasonPhrase] :: ServantErr -> String [errBody] :: ServantErr -> ByteString [errHeaders] :: ServantErr -> [Header] responseServantErr :: ServantErr -> Response -- | err300 Multiple Choices -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err300 { errBody = "I can't choose." }
--
err300 :: ServantErr
-- | err301 Moved Permanently
--
-- Example:
--
-- -- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err301 --err301 :: ServantErr -- | err302 Found -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err302 --err302 :: ServantErr -- | err303 See Other -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err303 --err303 :: ServantErr -- | err304 Not Modified -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err304 --err304 :: ServantErr -- | err305 Use Proxy -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err305 --err305 :: ServantErr -- | err307 Temporary Redirect -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err307 --err307 :: ServantErr -- | err400 Bad Request -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err400 { errBody = "Your request makes no sense to me." }
--
err400 :: ServantErr
-- | err401 Unauthorized
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err401 { errBody = "Your credentials are invalid." }
--
err401 :: ServantErr
-- | err402 Payment Required
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err402 { errBody = "You have 0 credits. Please give me $$$." }
--
err402 :: ServantErr
-- | err403 Forbidden
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err403 { errBody = "Please login first." }
--
err403 :: ServantErr
-- | err404 Not Found
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
--
err404 :: ServantErr
-- | err405 Method Not Allowed
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
--
err405 :: ServantErr
-- | err406 Not Acceptable
--
-- Example:
--
-- -- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err406 --err406 :: ServantErr -- | err407 Proxy Authentication Required -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err407 --err407 :: ServantErr -- | err409 Conflict -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
--
err409 :: ServantErr
-- | err410 Gone
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
--
err410 :: ServantErr
-- | err411 Length Required
--
-- Example:
--
-- -- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err411 --err411 :: ServantErr -- | err412 Precondition Failed -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
--
err412 :: ServantErr
-- | err413 Request Entity Too Large
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err413 { errBody = "Request exceeded 64k." }
--
err413 :: ServantErr
-- | err414 Request-URI Too Large
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err414 { errBody = "Maximum length is 64." }
--
err414 :: ServantErr
-- | err415 Unsupported Media Type
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err415 { errBody = "Supported media types: gif, png" }
--
err415 :: ServantErr
-- | err416 Request range not satisfiable
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err416 { errBody = "Valid range is [0, 424242]." }
--
err416 :: ServantErr
-- | err417 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
--
err417 :: ServantErr
-- | err500 Internal Server Error
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
--
err500 :: ServantErr
-- | err501 Not Implemented
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
--
err501 :: ServantErr
-- | err502 Bad Gateway
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
--
err502 :: ServantErr
-- | err503 Service Unavailable
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err503 { errBody = "We're rewriting in PHP." }
--
err503 :: ServantErr
-- | err504 Gateway Time-out
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
--
err504 :: ServantErr
-- | err505 HTTP Version not supported
--
-- Example usage:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err505 { errBody = "I support HTTP/4.0 only." }
--
err505 :: ServantErr
instance GHC.Read.Read Servant.Server.Internal.ServantErr.ServantErr
instance GHC.Classes.Eq Servant.Server.Internal.ServantErr.ServantErr
instance GHC.Show.Show Servant.Server.Internal.ServantErr.ServantErr
instance GHC.Exception.Exception Servant.Server.Internal.ServantErr.ServantErr
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
-- | The result of matching against a path in the route tree.
data RouteResult a
-- | Keep trying other paths. The ServantErr should only be 404,
-- 405 or 406.
Fail :: ServantErr -> RouteResult a
-- | Don't try other paths.
FailFatal :: !ServantErr -> RouteResult a
Route :: !a -> RouteResult a
toApplication :: RoutingApplication -> Application
-- | A Delayed is a representation of a handler with scheduled
-- delayed checks that can trigger errors.
--
-- Why would we want to delay checks?
--
-- There are two reasons:
--
-- -- 404 -- 405 (bad method) -- 401 (unauthorized) -- 415 (unsupported media type) -- 400 (bad request) -- 406 (not acceptable) ---- -- Therefore, while routing, we delay most checks so that they will -- ultimately occur in the right order. -- -- A Delayed contains three 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 = ... ---- | If you use Capture in one of the endpoints for your API, this -- automatically requires your server-side handler to be a function that -- takes an argument of the type specified by the Capture. This -- lets servant worry about getting it from the URL and turning it into a -- value of the type you specify. -- -- You can control how it'll be converted from Text to your type -- by simply providing an instance of FromHttpApiData for your -- type. -- -- Example: -- --
-- type MyApi = "books" :> Capture "isbn" Text :> Get '[JSON] Book -- -- server :: Server MyApi -- server = getBook -- where getBook :: Text -> ExceptT ServantErr IO Book -- getBook isbn = ... --allowedMethodHead :: Method -> Request -> Bool allowedMethod :: Method -> Request -> Bool processMethodRouter :: Maybe (ByteString, ByteString) -> Status -> Method -> Maybe [(HeaderName, ByteString)] -> Request -> RouteResult Response methodCheck :: Method -> Request -> IO (RouteResult ()) acceptCheck :: (AllMime list) => Proxy list -> ByteString -> IO (RouteResult ()) methodRouter :: (AllCTRender ctypes a) => Method -> Proxy ctypes -> Status -> Delayed (ExceptT ServantErr IO a) -> Router methodRouterHeaders :: (GetHeaders (Headers h v), AllCTRender ctypes v) => Method -> Proxy ctypes -> Status -> Delayed (ExceptT ServantErr IO (Headers h v)) -> Router -- | If you use Header in one of the endpoints for your API, this -- automatically requires your server-side handler to be a function that -- takes an argument of the type specified by Header. This lets -- servant worry about extracting it from the request and turning it into -- a value of the type you specify. -- -- All it asks is for a FromHttpApiData instance. -- -- Example: -- --
-- newtype Referer = Referer Text -- deriving (Eq, Show, FromHttpApiData) -- -- -- GET /view-my-referer -- type MyApi = "view-my-referer" :> Header "Referer" Referer :> Get '[JSON] Referer -- -- server :: Server MyApi -- server = viewReferer -- where viewReferer :: Referer -> ExceptT ServantErr IO referer -- viewReferer referer = return referer ---- | If you use QueryParam "author" Text in one of the -- endpoints for your API, this automatically requires your server-side -- handler to be a function that takes an argument of type -- Maybe Text. -- -- This lets servant worry about looking it up in the query string and -- turning it into a value of the type you specify, enclosed in -- Maybe, because it may not be there and servant would then hand -- you Nothing. -- -- You can control how it'll be converted from Text to your type -- by simply providing an instance of FromHttpApiData for your -- type. -- -- Example: -- --
-- type MyApi = "books" :> QueryParam "author" Text :> Get '[JSON] [Book] -- -- server :: Server MyApi -- server = getBooksBy -- where getBooksBy :: Maybe Text -> ExceptT ServantErr IO [Book] -- getBooksBy Nothing = ...return all books... -- getBooksBy (Just author) = ...return books by the given author... ---- | If you use QueryParams "authors" Text in one of the -- endpoints for your API, this automatically requires your server-side -- handler to be a function that takes an argument of type -- [Text]. -- -- This lets servant worry about looking up 0 or more values in the query -- string associated to authors and turning each of them into a -- value of the type you specify. -- -- You can control how the individual values are converted from -- Text to your type by simply providing an instance of -- FromHttpApiData for your type. -- -- Example: -- --
-- type MyApi = "books" :> QueryParams "authors" Text :> Get '[JSON] [Book] -- -- server :: Server MyApi -- server = getBooksBy -- where getBooksBy :: [Text] -> ExceptT ServantErr IO [Book] -- getBooksBy authors = ...return all books by these authors... ---- | If you use QueryFlag "published" in one of the -- endpoints for your API, this automatically requires your server-side -- handler to be a function that takes an argument of type Bool. -- -- Example: -- --
-- type MyApi = "books" :> QueryFlag "published" :> Get '[JSON] [Book] -- -- server :: Server MyApi -- server = getBooks -- where getBooks :: Bool -> ExceptT ServantErr IO [Book] -- getBooks onlyPublished = ...return all books, or only the ones that are already published, depending on the argument... ---- | Just pass the request to the underlying application and serve its -- response. -- -- Example: -- --
-- type MyApi = "images" :> Raw -- -- server :: Server MyApi -- server = serveDirectory "/var/www/images" ---- | If you use ReqBody in one of the endpoints for your API, this -- automatically requires your server-side handler to be a function that -- takes an argument of the type specified by ReqBody. The -- Content-Type header is inspected, and the list provided is -- used to attempt deserialization. If the request does not have a -- Content-Type header, it is treated as -- application/octet-stream (as specified in RFC7231. -- This lets servant worry about extracting it from the request and -- turning it into a value of the type you specify. -- -- All it asks is for a FromJSON instance. -- -- Example: -- --
-- type MyApi = "books" :> ReqBody '[JSON] Book :> Post '[JSON] Book -- -- server :: Server MyApi -- server = postBook -- where postBook :: Book -> ExceptT ServantErr IO Book -- postBook book = ...insert into your db... ---- | Make sure the incoming request starts with "/path", strip it -- and pass the rest of the request path to sublayout. -- | Basic Authentication pathIsEmpty :: Request -> Bool ct_wildcard :: ByteString instance (Servant.Server.Internal.HasServer a context, Servant.Server.Internal.HasServer b context) => Servant.Server.Internal.HasServer (a Servant.API.Alternative.:<|> b) context instance forall (k :: BOX) (capture :: GHC.TypeLits.Symbol) a (sublayout :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol capture, Web.HttpApiData.Internal.FromHttpApiData a, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (Servant.API.Capture.Capture capture a Servant.API.Sub.:> sublayout) context instance forall (k :: BOX) (method :: k) (status :: GHC.TypeLits.Nat) (ctypes :: [*]) a (context :: [*]). (Servant.API.ContentTypes.AllCTRender ctypes a, Servant.API.Verbs.ReflectMethod method, GHC.TypeLits.KnownNat status) => Servant.Server.Internal.HasServer (Servant.API.Verbs.Verb method status ctypes a) context instance forall (k :: BOX) (method :: k) (status :: GHC.TypeLits.Nat) (ctypes :: [*]) (h :: [*]) a (context :: [*]). (Servant.API.ContentTypes.AllCTRender ctypes a, Servant.API.Verbs.ReflectMethod method, GHC.TypeLits.KnownNat status, Servant.API.ResponseHeaders.GetHeaders (Servant.API.ResponseHeaders.Headers h a)) => Servant.Server.Internal.HasServer (Servant.API.Verbs.Verb method status ctypes (Servant.API.ResponseHeaders.Headers h a)) context instance forall (k :: BOX) (sym :: GHC.TypeLits.Symbol) a (sublayout :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol sym, Web.HttpApiData.Internal.FromHttpApiData a, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (Servant.API.Header.Header sym a Servant.API.Sub.:> sublayout) context instance forall (k :: BOX) (sym :: GHC.TypeLits.Symbol) a (sublayout :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol sym, Web.HttpApiData.Internal.FromHttpApiData a, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (Servant.API.QueryParam.QueryParam sym a Servant.API.Sub.:> sublayout) context instance forall (k :: BOX) (sym :: GHC.TypeLits.Symbol) a (sublayout :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol sym, Web.HttpApiData.Internal.FromHttpApiData a, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (Servant.API.QueryParam.QueryParams sym a Servant.API.Sub.:> sublayout) context instance forall (k :: BOX) (sym :: GHC.TypeLits.Symbol) (sublayout :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol sym, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (Servant.API.QueryParam.QueryFlag sym Servant.API.Sub.:> sublayout) context instance Servant.Server.Internal.HasServer Servant.API.Raw.Raw context instance forall (k :: BOX) (list :: [*]) a (sublayout :: k) (context :: [*]). (Servant.API.ContentTypes.AllCTUnrender list a, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (Servant.API.ReqBody.ReqBody list a Servant.API.Sub.:> sublayout) context instance forall (k :: BOX) (path :: GHC.TypeLits.Symbol) (sublayout :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol path, Servant.Server.Internal.HasServer sublayout context) => Servant.Server.Internal.HasServer (path Servant.API.Sub.:> sublayout) context instance forall (k :: BOX) (api :: k) (context :: [*]). Servant.Server.Internal.HasServer api context => Servant.Server.Internal.HasServer (Servant.API.RemoteHost.RemoteHost Servant.API.Sub.:> api) context instance forall (k :: BOX) (api :: k) (context :: [*]). Servant.Server.Internal.HasServer api context => Servant.Server.Internal.HasServer (Servant.API.IsSecure.IsSecure Servant.API.Sub.:> api) context instance forall (k :: BOX) (api :: k) (context :: [*]). Servant.Server.Internal.HasServer api context => Servant.Server.Internal.HasServer (Data.Vault.Lazy.Vault Servant.API.Sub.:> api) context instance forall (k :: BOX) (api :: k) (context :: [*]). Servant.Server.Internal.HasServer api context => Servant.Server.Internal.HasServer (Network.HTTP.Types.Version.HttpVersion Servant.API.Sub.:> api) context instance forall (k :: BOX) (realm :: GHC.TypeLits.Symbol) usr (api :: k) (context :: [*]). (GHC.TypeLits.KnownSymbol realm, Servant.Server.Internal.HasServer api context, Servant.Server.Internal.Context.HasContextEntry context (Servant.Server.Internal.BasicAuth.BasicAuthCheck usr)) => Servant.Server.Internal.HasServer (Servant.API.BasicAuth.BasicAuth realm usr Servant.API.Sub.:> api) context instance (Servant.Server.Internal.Context.HasContextEntry context (Servant.Server.Internal.Context.NamedContext name subContext), Servant.Server.Internal.HasServer subApi subContext) => Servant.Server.Internal.HasServer (Servant.API.WithNamedContext.WithNamedContext name subContext subApi) context -- | This module lets you implement Servers for defined APIs. You'll -- most likely just need serve. module Servant.Server -- | serve allows you to implement an API and produce a wai -- Application. -- -- Example: -- --
-- 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 layout '[]) => Proxy layout -> Server layout -> Application serveWithContext :: (HasServer layout context) => Proxy layout -> Context context -> Server layout -> Application toApplication :: RoutingApplication -> Application class HasServer layout context where type family ServerT layout (m :: * -> *) :: * route :: HasServer layout context => Proxy layout -> Context context -> Delayed (Server layout) -> Router type Server layout = ServerT layout (ExceptT ServantErr IO) enter :: Enter typ arg ret => arg -> typ -> ret -- | A natural transformation from m to n. Used to -- enter particular datatypes. newtype (:~>) m n Nat :: (forall a. m a -> n a) -> (:~>) m n [unNat] :: (:~>) m n -> forall a. m a -> n a -- | Like lift. liftNat :: (MonadTrans t, Monad m) => m :~> t m runReaderTNat :: r -> (ReaderT r m :~> m) evalStateTLNat :: Monad m => s -> (StateT s m :~> m) evalStateTSNat :: Monad m => s -> (StateT s m :~> m) -- | Like logWriterTSNat, but for strict WriterT. logWriterTLNat :: MonadIO m => (w -> IO ()) -> (WriterT w m :~> m) -- | Log the contents of WriterT with the function provided as the -- first argument, and return the value of the WriterT -- computation logWriterTSNat :: MonadIO m => (w -> IO ()) -> (WriterT w m :~> m) -- | Like mmorph's hoist. hoistNat :: (MFunctor t, Monad m) => (m :~> n) -> (t m :~> t n) -- | Like mmorph's embed. embedNat :: (MMonad t, Monad n) => (m :~> t n) -> (t m :~> t n) -- | Like mmorph's squash. squashNat :: (Monad m, MMonad t) => t (t m) :~> t m -- | Like mmorph's generalize. generalizeNat :: Applicative m => Identity :~> m -- | Apply a transformation to the response of a Router. tweakResponse :: (RouteResult Response -> RouteResult Response) -> Router -> Router -- | 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 enter.) 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) -- | 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 :: 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 ServantErr ServantErr :: Int -> String -> ByteString -> [Header] -> ServantErr [errHTTPCode] :: ServantErr -> Int [errReasonPhrase] :: ServantErr -> String [errBody] :: ServantErr -> ByteString [errHeaders] :: ServantErr -> [Header] -- | err300 Multiple Choices -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err300 { errBody = "I can't choose." }
--
err300 :: ServantErr
-- | err301 Moved Permanently
--
-- Example:
--
-- -- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err301 --err301 :: ServantErr -- | err302 Found -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err302 --err302 :: ServantErr -- | err303 See Other -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err303 --err303 :: ServantErr -- | err304 Not Modified -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err304 --err304 :: ServantErr -- | err305 Use Proxy -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err305 --err305 :: ServantErr -- | err307 Temporary Redirect -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err307 --err307 :: ServantErr -- | err400 Bad Request -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err400 { errBody = "Your request makes no sense to me." }
--
err400 :: ServantErr
-- | err401 Unauthorized
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err401 { errBody = "Your credentials are invalid." }
--
err401 :: ServantErr
-- | err402 Payment Required
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err402 { errBody = "You have 0 credits. Please give me $$$." }
--
err402 :: ServantErr
-- | err403 Forbidden
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err403 { errBody = "Please login first." }
--
err403 :: ServantErr
-- | err404 Not Found
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err404 { errBody = "(╯°□°)╯︵ ┻━┻)." }
--
err404 :: ServantErr
-- | err405 Method Not Allowed
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err405 { errBody = "Your account privileges does not allow for this. Please pay $$$." }
--
err405 :: ServantErr
-- | err406 Not Acceptable
--
-- Example:
--
-- -- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err406 --err406 :: ServantErr -- | err407 Proxy Authentication Required -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err407 --err407 :: ServantErr -- | err409 Conflict -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err409 { errBody = "Transaction conflicts with 59879cb56c7c159231eeacdd503d755f7e835f74" }
--
err409 :: ServantErr
-- | err410 Gone
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err410 { errBody = "I know it was here at some point, but.. I blame bad luck." }
--
err410 :: ServantErr
-- | err411 Length Required
--
-- Example:
--
-- -- failingHandler :: ExceptT ServantErr IO () -- failingHandler = throwErr err411 --err411 :: ServantErr -- | err412 Precondition Failed -- -- Example: -- --
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err412 { errBody = "Precondition fail: x < 42 && y > 57" }
--
err412 :: ServantErr
-- | err413 Request Entity Too Large
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err413 { errBody = "Request exceeded 64k." }
--
err413 :: ServantErr
-- | err414 Request-URI Too Large
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err414 { errBody = "Maximum length is 64." }
--
err414 :: ServantErr
-- | err415 Unsupported Media Type
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err415 { errBody = "Supported media types: gif, png" }
--
err415 :: ServantErr
-- | err416 Request range not satisfiable
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err416 { errBody = "Valid range is [0, 424242]." }
--
err416 :: ServantErr
-- | err417 Expectation Failed
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err417 { errBody = "I found a quux in the request. This isn't going to work." }
--
err417 :: ServantErr
-- | err500 Internal Server Error
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err500 { errBody = "Exception in module A.B.C:55. Have a great day!" }
--
err500 :: ServantErr
-- | err501 Not Implemented
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err501 { errBody = "/v1/foo is not supported with quux in the request." }
--
err501 :: ServantErr
-- | err502 Bad Gateway
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err502 { errBody = "Tried gateway foo, bar, and baz. None responded." }
--
err502 :: ServantErr
-- | err503 Service Unavailable
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err503 { errBody = "We're rewriting in PHP." }
--
err503 :: ServantErr
-- | err504 Gateway Time-out
--
-- Example:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err504 { errBody = "Backend foobar did not respond in 5 seconds." }
--
err504 :: ServantErr
-- | err505 HTTP Version not supported
--
-- Example usage:
--
--
-- failingHandler :: ExceptT ServantErr IO ()
-- failingHandler = throwErr $ err505 { errBody = "I support HTTP/4.0 only." }
--
err505 :: ServantErr
-- | This module defines a sever-side handler that lets you serve static
-- files.
--
-- -- type MyApi = "static" :> Raw -- -- server :: Server MyApi -- server = serveDirectory "/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 serveDirectory handler in the last -- position, because servant will try to match the handlers in -- order. serveDirectory :: FilePath -> Server Raw module Servant -- | A concrete, poly-kinded proxy type data Proxy (t :: k) :: k -> * Proxy :: Proxy 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 -- | Handlers for AuthProtected resources -- -- NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE newtype AuthHandler r usr AuthHandler :: (r -> ExceptT ServantErr IO usr) -> AuthHandler r usr [unAuthHandler] :: AuthHandler r usr -> r -> ExceptT ServantErr IO usr -- | NOTE: THIS API IS EXPERIMENTAL AND SUBJECT TO CHANGE mkAuthHandler :: (r -> ExceptT ServantErr IO usr) -> AuthHandler r usr -- | Known orphan instance. instance GHC.Generics.Selector Servant.Server.Experimental.Auth.S1_0_0AuthHandler instance GHC.Generics.Constructor Servant.Server.Experimental.Auth.C1_0AuthHandler instance GHC.Generics.Datatype Servant.Server.Experimental.Auth.D1AuthHandler instance GHC.Generics.Generic (Servant.Server.Experimental.Auth.AuthHandler r usr) instance forall (k :: BOX) (k1 :: BOX) (tag :: k1) (api :: k) (context :: [*]). (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