mellon-web-0.7.0.1: src/Mellon/Web/Server/DocsAPI.hs
{-|
Module : Mellon.Web.Server.DocsAPI
Description : A documentation-annotated REST web service for @mellon-core@ controllers
Copyright : (c) 2016, Drew Hess
License : BSD3
Maintainer : Drew Hess <src@drewhess.com>
Stability : experimental
Portability : non-portable
This module extends the standard 'MellonAPI' with a documentation
resource, in case you want to provide on-line documentation for the
API. In every other way, it is identical to the 'MellonAPI' service.
-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeOperators #-}
module Mellon.Web.Server.DocsAPI
( -- * Types
DocsAPI
-- * Servant / WAI functions
, docsAPI
, docsApp
, docsServer
) where
import Data.ByteString.Lazy (ByteString)
import Data.Text.Lazy (pack)
import Data.Text.Lazy.Encoding (encodeUtf8)
import Mellon.Controller (Controller)
import Network.HTTP.Types (ok200)
import Network.Wai (Application, responseLBS)
import Servant ((:>), (:<|>)(..), Raw, Proxy(..), Server, serve)
import Servant.Docs (DocIntro(..), docsWithIntros, markdown)
import Mellon.Web.Server.API (MellonAPI, mellonAPI, server)
-- | Extends 'MellonAPI' with a documentation resource.
--
-- The documentation resource is available via the @GET /docs@ method.
type DocsAPI = MellonAPI :<|> "docs" :> Raw
-- | A 'Proxy' for 'DocsAPI', exported in order to make it possible to
-- extend the API.
docsAPI :: Proxy DocsAPI
docsAPI = Proxy
docsBS :: ByteString
docsBS = encodeUtf8 . pack . markdown $ docsWithIntros [intro] mellonAPI
where
intro = DocIntro "Mellon API" []
-- | A 'Server' which serves the 'DocsAPI' on the given 'Controller'.
--
-- Normally you will just use 'docsApp', but this function is exported so
-- that you can extend/wrap 'DocsAPI'.
docsServer :: Controller d -> Server DocsAPI
docsServer cc = server cc :<|> serveDocs
where
serveDocs _ respond =
respond $ responseLBS ok200 [plain] docsBS
plain = ("Content-Type", "text/plain")
-- | A WAI 'Network.Wai.Application' which runs the service, using the
-- given 'Controller'
docsApp :: Controller d -> Application
docsApp = serve docsAPI . docsServer