-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A family of combinators for defining webservices APIs and serving them -- -- Interpret a Servant API as a Snap server, using any Snaplets you like. -- -- You can learn about the basics of servant in the Servant -- tutorial, and about the basics of Snap at the Snaplets -- tutorial -- -- Here is a runnable example, with comments, that defines a dummy -- API and implements a webserver that serves this API, using this -- package. One route delegates to the Auth snaplet, another -- delegates to Heist. -- -- CHANGELOG @package servant-snap @version 0.8.4 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) 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.PathInfo rqPath :: Request -> ByteString pathInfo :: Request -> [Text] pathSafeTail :: Request -> ([ByteString], [ByteString]) reqSafeTail :: Request -> Request reqNoPath :: Request -> Request -- | Like `null . pathInfo`, but works with redundant trailing slashes. pathIsEmpty :: Request -> Bool splitMatrixParameters :: Text -> (Text, Text) parsePathInfo :: Request -> [Text] -- | Returns a processed pathInfo from the request. -- -- In order to handle matrix parameters in the request correctly, the raw -- pathInfo needs to be processed, so routing works as intended. Therefor -- this function should be used to access the pathInfo for routing -- purposes. processedPathInfo :: Request -> [Text] 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] setHeaders :: [Header] -> Response -> Response responseServantErr :: ServantErr -> Response -- | Terminate request handling with a ServantErr via -- finishWith throwError :: MonadSnap m => ServantErr -> m a err300 :: ServantErr err301 :: ServantErr err302 :: ServantErr err303 :: ServantErr err304 :: ServantErr err305 :: ServantErr err307 :: ServantErr err400 :: ServantErr err401 :: ServantErr err402 :: ServantErr err403 :: ServantErr err404 :: ServantErr err405 :: ServantErr err406 :: ServantErr err407 :: ServantErr err409 :: ServantErr err410 :: ServantErr err411 :: ServantErr err412 :: ServantErr err413 :: ServantErr err414 :: ServantErr err415 :: ServantErr err416 :: ServantErr err417 :: ServantErr err500 :: ServantErr err501 :: ServantErr err502 :: ServantErr err503 :: ServantErr err504 :: ServantErr 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 module Servant.Server.Internal.SnapShims type Application m = Request -> (Response -> m Response) -> m Response snapToApplication :: MonadSnap m => m () -> Application m snapToApplication' :: MonadSnap m => m a -> Application m applicationToSnap :: MonadSnap m => Application m -> m () addHeaders :: HasHeaders a => a -> Headers -> a unSnapMethod :: Method -> ByteString ok200 :: Status noContent204 :: Status created201 :: Status badRequest400 :: Status notFound404 :: Status methodNotAllowed405 :: Status unsupportedMediaType415 :: Status initThunk :: IO a -> IO (IO a) module Servant.Server.Internal.RoutingApplication type RoutingApplication m = Request " the request, the field 'pathInfo' may be modified by url routing" -> (RouteResult Response -> m Response) -> m Response -- | 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 :: forall m. MonadSnap m => RoutingApplication m -> Application m responseLBS :: Status -> [(CI ByteString, ByteString)] -> ByteString -> Response runAction :: MonadSnap m => Delayed m env (m a) -> env -> Request -> (RouteResult Response -> m r) -> (a -> RouteResult Response) -> m r data Delayed m env c [Delayed] :: {capturesD :: env -> DelayedM m captures, methodD :: DelayedM m (), authD :: DelayedM m auth, acceptD :: DelayedM m (), contentD :: DelayedM m contentType, paramsD :: DelayedM m params, headersD :: DelayedM m headers, bodyD :: contentType -> DelayedM m body, serverD :: captures -> params -> headers -> auth -> body -> Request -> RouteResult c} -> Delayed m env c newtype DelayedM m a DelayedM :: (Request -> m (RouteResult a)) -> DelayedM m a [runDelayedM] :: DelayedM m a -> Request -> m (RouteResult a) -- | A Delayed without any stored checks. emptyDelayed :: Monad m => Proxy (m :: * -> *) -> RouteResult a -> Delayed m env a -- | Fail with the option to recover. delayedFail :: Monad m => ServantErr -> DelayedM m a -- | Fail fatally, i.e., without any option to recover. delayedFailFatal :: Monad m => ServantErr -> DelayedM m a -- | Gain access to the incoming request. withRequest :: (Request -> DelayedM m a) -> DelayedM m a -- | Add a capture to the end of the capture block. addCapture :: forall env a b captured m. Monad m => Delayed m env (a -> b) -> (captured -> DelayedM m a) -> Delayed m (captured, env) b -- | Add a parameter check to the end of the params block addParameterCheck :: Monad m => Delayed m env (a -> b) -> DelayedM m a -> Delayed m env b -- | Add a header check to the end of the headers block addHeaderCheck :: Monad m => Delayed m env (a -> b) -> DelayedM m a -> Delayed m env b -- | Add a method check to the end of the method block. addMethodCheck :: Monad m => Delayed m env a -> DelayedM m () -> Delayed m env a -- | Add an auth check to the end of the auth block. addAuthCheck :: Monad m => Delayed m env (a -> b) -> DelayedM m a -> Delayed m env b -- | Add a content type and body checks around parameter checks. -- -- We'll report failed content type check (415), before trying to parse -- query parameters (400). Which, in turn, happens before request body -- parsing. addBodyCheck :: Monad m => Delayed m env (a -> b) -> DelayedM m c -> (c -> DelayedM m a) -> Delayed m env b -- | Add an accept header check before handling parameters. In principle, -- we'd like to take a bad body (400) response take precedence over a -- failed accept check (406). BUT to allow streaming the body, we cannot -- run the body check and then still backtrack. We therefore do the -- accept check before the body check, when we can still backtrack. There -- are other solutions to this, but they'd be more complicated (such as -- delaying the body check further so that it can still be run in a -- situation where we'd otherwise report 406). addAcceptCheck :: Monad m => Delayed m env a -> DelayedM m () -> Delayed m env 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 m env (a -> b) -> (Request -> a) -> Delayed m env b -- | 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 :: Monad m => Delayed m env a -> env -> Request -> m (RouteResult a) 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 m env) instance GHC.Base.Monad m => GHC.Base.Functor (Servant.Server.Internal.RoutingApplication.DelayedM m) instance GHC.Base.Monad m => GHC.Base.Applicative (Servant.Server.Internal.RoutingApplication.DelayedM m) instance GHC.Base.Monad m => GHC.Base.Monad (Servant.Server.Internal.RoutingApplication.DelayedM m) instance Control.Monad.IO.Class.MonadIO m => Control.Monad.IO.Class.MonadIO (Servant.Server.Internal.RoutingApplication.DelayedM m) instance (GHC.Base.Monad m, Snap.Internal.Core.MonadSnap m) => GHC.Base.Alternative (Servant.Server.Internal.RoutingApplication.DelayedM m) instance Control.Monad.Trans.Class.MonadTrans Servant.Server.Internal.RoutingApplication.DelayedM module Servant.Server.Internal.Router type Router (m :: * -> *) env = Router' m env (RoutingApplication m) -- | Internal representation of a router. data Router' (m :: * -> *) env a StaticRouter :: Map Text (Router' m env a) -> [env -> a] -> Router' env a CaptureRouter :: Router' m (Text, env) a -> Router' env a CaptureAllRouter :: Router' m ([Text], env) a -> Router' env a RawRouter :: (env -> a) -> Router' env a Choice :: Router' m env a -> Router' m env a -> Router' env a pathRouter :: Text -> Router' m env a -> Router' m env a leafRouter :: (env -> a) -> Router' m env a -- | Smart constructor for the choice between routers. We currently -- optimize the following cases: -- --
-- 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 :: MonadSnap m => FilePath -> Server Raw context 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