-- 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: -- --
    --
  1. In a straight-forward implementation, the order in which we -- perform checks will determine the error we generate. This is because -- once an error occurs, we would abort and not perform any subsequent -- checks, but rather return the current error.
  2. --
-- -- This is not a necessity: we could continue doing other checks, and -- choose the preferred error. However, that would in general mean more -- checking, which leads us to the other reason. -- --
    --
  1. We really want to avoid doing certain checks too early. For -- example, captures involve parsing, and are much more costly than -- static route matches. In particular, if several paths contain the -- "same" capture, we'd like as much as possible to avoid trying the same -- parse many times. Also tricky is the request body. Again, this -- involves parsing, but also, WAI makes obtaining the request body a -- side-effecting operation. We could/can work around this by manually -- caching the request body, but we'd rather keep the number of times we -- actually try to decode the request body to an absolute minimum.
  2. --
-- -- We prefer to have the following relative priorities of error codes: -- --
--   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: -- --
    --
  1. Delayed captures. These can actually cause 404, and while they're -- costly, they should be done first among the delayed checks (at least -- as long as we do not decouple the check order from the error -- reporting, see above). Delayed captures can provide inputs to the -- actual handler.
  2. --
  3. Method check(s). This can cause a 405. On success, it does not -- provide an input for the handler. Method checks are comparatively -- cheap.
  4. --
  5. Body and accept header checks. The request body check can cause -- both 400 and 415. This provides an input to the handler. The accept -- header check can be performed as the final computation in this block. -- It can cause a 406.
  6. --
data Delayed c Delayed :: IO (RouteResult captures) -> IO (RouteResult ()) -> IO (RouteResult auth) -> IO (RouteResult body) -> (captures -> auth -> body -> RouteResult c) -> Delayed c [capturesD] :: Delayed c -> IO (RouteResult captures) [methodD] :: Delayed c -> IO (RouteResult ()) [authD] :: Delayed c -> IO (RouteResult auth) [bodyD] :: Delayed c -> IO (RouteResult body) [serverD] :: Delayed c -> (captures -> auth -> body -> RouteResult c) -- | Add a capture to the end of the capture block. addCapture :: Delayed (a -> b) -> IO (RouteResult a) -> Delayed b -- | Add a method check to the end of the method block. addMethodCheck :: Delayed a -> IO (RouteResult ()) -> Delayed a -- | Add an auth check to the end of the auth block. addAuthCheck :: Delayed (a -> b) -> IO (RouteResult a) -> Delayed b -- | Add a body check to the end of the body block. addBodyCheck :: Delayed (a -> b) -> IO (RouteResult a) -> Delayed b -- | Add an accept header check to the end of the body block. The accept -- header check should occur after the body check, but this will be the -- case, because the accept header check is only scheduled by the method -- combinators. addAcceptCheck :: Delayed a -> IO (RouteResult ()) -> Delayed a -- | Many combinators extract information that is passed to the handler -- without the possibility of failure. In such a case, -- passToServer can be used. passToServer :: Delayed (a -> b) -> a -> Delayed b -- | The combination 'IO . RouteResult' is a monad, but we don't explicitly -- wrap it in a newtype in order to make it an instance. This is the -- >>= of that monad. -- -- We stop on the first error. bindRouteResults :: IO (RouteResult a) -> (a -> IO (RouteResult b)) -> IO (RouteResult b) -- | Common special case of bindRouteResults, corresponding to -- liftM2. combineRouteResults :: (a -> b -> c) -> IO (RouteResult a) -> IO (RouteResult b) -> IO (RouteResult c) -- | Run a delayed server. Performs all scheduled operations in order, and -- passes the results from the capture and body blocks on to the actual -- handler. -- -- This should only be called once per request; otherwise the guarantees -- about effect and HTTP error ordering break down. runDelayed :: Delayed a -> IO (RouteResult a) -- | Runs a delayed server and the resulting action. Takes a continuation -- that lets us send a response. Also takes a continuation for how to -- turn the result of the delayed server into a response. runAction :: Delayed (ExceptT ServantErr IO a) -> (RouteResult Response -> IO r) -> (a -> RouteResult Response) -> IO r instance GHC.Base.Functor Servant.Server.Internal.RoutingApplication.RouteResult instance GHC.Read.Read a => GHC.Read.Read (Servant.Server.Internal.RoutingApplication.RouteResult a) instance GHC.Show.Show a => GHC.Show.Show (Servant.Server.Internal.RoutingApplication.RouteResult a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Servant.Server.Internal.RoutingApplication.RouteResult a) instance GHC.Base.Functor Servant.Server.Internal.RoutingApplication.Delayed module Servant.Server.Internal.BasicAuth -- | 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 -- | 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) -- | Internal method to make a basic-auth challenge mkBAChallengerHdr :: ByteString -> Header -- | Find and decode an Authorization header from the request as -- Basic Auth decodeBAHdr :: Request -> Maybe BasicAuthData -- | Run and check basic authentication, returning the appropriate http -- error per the spec. runBasicAuth :: Request -> ByteString -> BasicAuthCheck usr -> IO (RouteResult usr) instance GHC.Generics.Selector Servant.Server.Internal.BasicAuth.S1_0_0BasicAuthCheck instance GHC.Generics.Constructor Servant.Server.Internal.BasicAuth.C1_0BasicAuthCheck instance GHC.Generics.Datatype Servant.Server.Internal.BasicAuth.D1BasicAuthCheck instance GHC.Generics.Constructor Servant.Server.Internal.BasicAuth.C1_3BasicAuthResult instance GHC.Generics.Constructor Servant.Server.Internal.BasicAuth.C1_2BasicAuthResult instance GHC.Generics.Constructor Servant.Server.Internal.BasicAuth.C1_1BasicAuthResult instance GHC.Generics.Constructor Servant.Server.Internal.BasicAuth.C1_0BasicAuthResult instance GHC.Generics.Datatype Servant.Server.Internal.BasicAuth.D1BasicAuthResult instance GHC.Base.Functor Servant.Server.Internal.BasicAuth.BasicAuthCheck instance GHC.Generics.Generic (Servant.Server.Internal.BasicAuth.BasicAuthCheck usr) instance GHC.Base.Functor Servant.Server.Internal.BasicAuth.BasicAuthResult instance GHC.Generics.Generic (Servant.Server.Internal.BasicAuth.BasicAuthResult usr) instance GHC.Read.Read usr => GHC.Read.Read (Servant.Server.Internal.BasicAuth.BasicAuthResult usr) instance GHC.Show.Show usr => GHC.Show.Show (Servant.Server.Internal.BasicAuth.BasicAuthResult usr) instance GHC.Classes.Eq usr => GHC.Classes.Eq (Servant.Server.Internal.BasicAuth.BasicAuthResult usr) module Servant.Server.Internal.Router type Router = Router' RoutingApplication -- | Internal representation of a router. data Router' a -- | current request is passed to the router WithRequest :: (Request -> Router) -> Router' a -- | first path component used for lookup and removed afterwards StaticRouter :: (Map Text Router) -> Router' a -- | first path component used for lookup and removed afterwards DynamicRouter :: (Text -> Router) -> Router' a -- | to be used for routes that match an empty path LeafRouter :: a -> Router' a -- | left-biased choice between two routers Choice :: Router -> Router -> Router' a -- | Apply a transformation to the response of a Router. tweakResponse :: (RouteResult Response -> RouteResult Response) -> Router -> Router -- | Smart constructor for the choice between routers. We currently -- optimize the following cases: -- -- choice :: Router -> Router -> Router -- | Interpret a router as an application. runRouter :: Router -> RoutingApplication worseHTTPCode :: Int -> Int -> Bool instance GHC.Base.Functor Servant.Server.Internal.Router.Router' module Servant.Server.Internal.Enter class Enter typ arg ret | typ arg -> ret, typ ret -> arg 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) -- | 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 logWriterTSNat, but for strict WriterT. logWriterTLNat :: 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 instance (Servant.Server.Internal.Enter.Enter typ1 arg1 ret1, Servant.Server.Internal.Enter.Enter typ2 arg2 ret2, arg1 ~ arg2) => Servant.Server.Internal.Enter.Enter (typ1 Servant.API.Alternative.:<|> typ2) arg1 (ret1 Servant.API.Alternative.:<|> ret2) instance Servant.Server.Internal.Enter.Enter b arg ret => Servant.Server.Internal.Enter.Enter (a -> b) arg (a -> ret) instance Control.Category.Category (Servant.Server.Internal.Enter.:~>) instance Servant.Server.Internal.Enter.Enter (m a) (m Servant.Server.Internal.Enter.:~> n) (n a) module Servant.Server.Internal 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) -- | A server for a :<|> b first tries to match the -- request against the route represented by a and if it fails -- tries b. You must provide a request handler for each route. -- --
--   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. -- -- module Servant.Utils.StaticFiles -- | Serve anything under the specified directory as a Raw endpoint. -- --
--   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