packages feed

pdf-slave-server-0.1.1.0: src/Text/PDF/Slave/Server.hs

module Text.PDF.Slave.Server(
  -- * Server config
    ServerConfig(..)
  , readConfig
  -- * Server environment
  , ServerEnv
  , newServerEnv
  -- * Execution of server
  , pdfSlaveServerApp
  ) where

import Control.Monad
import Control.Monad.Error.Class
import Control.Monad.IO.Class
import Data.Aeson.WithField
import Data.Maybe
import Data.Proxy
import Servant.API
import Servant.API.Auth.Token
import Servant.Server
import Servant.Server.Auth.Token

import qualified Data.UUID.V4 as UUID

import Text.PDF.Slave.Server.API
import Text.PDF.Slave.Server.Config
import Text.PDF.Slave.Server.DB
import Text.PDF.Slave.Server.Monad

-- | Full Server API
type ServerAPI = PDFSlaveAPI :<|> AuthAPI

-- | WAI application of server
pdfSlaveServerApp :: ServerEnv -> Application
pdfSlaveServerApp e = serve (Proxy :: Proxy ServerAPI) $ enter (serverMtoHandler e) $
       pdfSlaveServer
  :<|> enter authToServerM (authServer :: ServerT AuthAPI AuthM)

-- | Implementation of main server API
pdfSlaveServer :: ServerT PDFSlaveAPI ServerM
pdfSlaveServer = renderTemplateEndpoint

-- | Implementation of 'RenderTemplateEndpoint'
renderTemplateEndpoint :: APIRenderBody
  -> MToken' '["render"]
  -> ServerM (OnlyId APIRenderId)
renderTemplateEndpoint APIRenderBody{..} token = do
  runAuth $ guardAuthToken token
  ServerConfig{..} <- getConfig
  n <- runQuery GetRenderQueueSize
  whenJust serverMaximumQueue $ \n' -> unless (n < n') $
    throwError $ err507 { errBody = "Rendering queue is full"}
  i <- maybe (liftIO UUID.nextRandom) (return . fromAPIRenderId) apiRenderBodyId
  runUpdate . AddRenderItem $ RenderItem {
      renderId       = RenderId i
    , renderTemplate = apiRenderBodyTemplate
    , renderInput    = apiRenderBodyInput
    , renderUrl      = apiRenderBodyUrl
    , renderToken    = unToken $ fromJust token -- already guarded Nothing
    }
  emitRenderItem -- awake workers
  return $ OnlyField . toAPIRenderId $ i

-- | Definition of 507 HTTP error `Insufficient Storage`
err507 :: ServantErr
err507 = ServantErr {
    errHTTPCode = 507
  , errReasonPhrase = "Insufficient Storage"
  , errBody = ""
  , errHeaders = []
  }