servant-rawm- Embed a raw 'Application' in a Servant API

CopyrightDennis Gosnell 2017
MaintainerDennis Gosnell (
Safe HaskellNone




This module exposes a RawM type that allows you to embed a WAI Application in your Servant API.

It is similar to Raw provided by Servant, but there is one big difference. RawM allows you to use monadic effects to create the Application.

What does this look like in practice? The following is an example of using RawM:

  type Api = "serve-directory-example" :> RawM

  serverRoot :: ServerT Api (ReaderT FilePath IO)
  serverRoot = rawEndpoint

  rawEndpoint :: ReaderT FilePath IO Application
  rawEndpoint = do
    filePath <- ask
    serveDirectoryWebApp filePath

  app :: FilePath -> Application
  app filePath =
    serve (Proxy :: Proxy Api) apiServer
      apiServer :: Server Api
      apiServer = enter (NT transformation) serverRoot

      transformation :: ReaderT FilePath IO a -> Handler a
      transformation readerT = liftIO $ runReaderT readerT filePath

Notice how the above rawEndpoint handler is able to get the filePath from the ReaderT. Using Servant's default Raw type, rawEndpoint would have to be written like the following:

  type Api' = "serve-directory-example" :> Raw

  serverRoot' :: ServerT Api (ReaderT FilePath IO)
  serverRoot' = rawEndpoint'

  rawEndpoint' :: Tagged (ReaderT FilePath IO) Application
  rawEndpoint' = ...

rawEndpoint' does not have access to the ReaderT monad, so there is no way to get the directory path.

RawM solves this problem by allowing the Application to be produced monadically.

There is an example in the source code repository that shows a more in-depth server, client, and documentation.


RawM API parameter

type RawM = RawM' FileServer Source #

Specialization of RawM' to FileServer. This can be used if you are using serveDirectoryWebApp, serveDirectoryFileServer, etc.

data RawM' serverType Source #

This is a type to use to define a Servant API. It signifies a route that allows embedding of a WAI Application. It is similar to Raw, but it has a HasServer instance that allows embedding of monadic effects. This should be more convenient than Raw.

The phantom type serverType is used for defining the HasDocs instance. There are instances for HasClient and HasServer for RawM' with a polymorphic phantom type, but there is only a HasDocs instance specified for RawM' FileServer. This allows the end-user to easily create a HasDocs instance for a custom Application.


type Client * (RawM' serverType) # 
type ServerT * (RawM' serverType) m # 
type ServerT * (RawM' serverType) m = m Application

data FileServer Source #

Used by RawM as a phantom type.

Helper functions for writing simple file servers

serveDirectoryWebApp :: Applicative m => FilePath -> ServerT (RawM' serverType) m Source #

Serve anything under the specified directory as a RawM' endpoint.

type MyApi = "static" :> RawM'

server :: ServerT MyApi m
server = serveDirectoryWebApp "/var/www"

would capture any request to /static/<something> and look for <something> under /var/www.

It will do its best to guess the MIME type for that file, based on the extension, and send an appropriate Content-Type header if possible.

If your goal is to serve HTML, CSS and Javascript files that use the rest of the API as a webapp backend, you will most likely not want the static files to be hidden behind a /static/ prefix. In that case, remember to put the serveDirectoryWebApp handler in the last position, because servant will try to match the handlers in order.

Corresponds to the defaultWebAppSettings StaticSettings value.

serveDirectoryWith :: Applicative m => StaticSettings -> ServerT (RawM' serverType) m Source #

Alias for staticApp. Lets you serve a directory with arbitrary StaticSettings. Useful when you want particular settings not covered by the four other variants. This is the most flexible method.