module Mongrel2 ( Handler , ConnectedHandler , mkHandler , withConnectedHandler , receiveRequest , sendReply -- Re-exported , Request(..) , UUID , ClientID ) where import Blaze.ByteString.Builder (Builder) import Data.Attoparsec import Mongrel2.Types (Request(..)) import Mongrel2.Parser (messageParser, UUID, ClientID) import Mongrel2.Response (mkResponse) import qualified System.ZMQ as ZMQ data Handler = Handler { handlerPullFrom :: String , handlerPublishTo :: String , handlerId :: Maybe String } data ConnectedHandler = ConnectedHandler { chPullSocket :: ZMQ.Socket ZMQ.Pull , chPublishSocket :: ZMQ.Socket ZMQ.Pub } -- | Create a new handler. @mkHandler pullFromAddress publishToAddress id@ -- creates a handler which pulls requests from @fromAddress@ and publishes -- replies to @publishAddress@. mkHandler :: String -> String -> Maybe String -> Handler mkHandler = Handler -- | Run an IO action with a connected handler. withConnectedHandler :: Handler -> (ConnectedHandler -> IO a) -> IO a withConnectedHandler h io = ZMQ.withContext 1 $ \c -> ZMQ.withSocket c ZMQ.Pull $ \s -> do ZMQ.withSocket c ZMQ.Pub $ \ps -> do -- Connect to the poll socket. ZMQ.connect s $ handlerPullFrom h -- Bind to publish socket. ZMQ.connect ps $ handlerPublishTo h case handlerId h of Nothing -> return () Just uuid -> ZMQ.setOption ps $ ZMQ.Identity uuid -- Run the action with the connected handler. io $ ConnectedHandler s ps -- | Receive a parsed request from the Mongrel2 server. Blocks until -- a message is received. receiveRequest :: ConnectedHandler -> IO Request receiveRequest handler = do msg <- ZMQ.receive (chPullSocket handler) [] -- Parse into a structured message. case parseOnly messageParser msg of Left errMsg -> -- Invalid message. This can only happen if there's -- an error in our parsing code or Mongrel2 itself. fail $ "Couldn't parse message: " ++ (show errMsg) Right m -> do -- Return the parsed message. return m -- | Send a reply to the Mongrel2 server. sendReply :: ConnectedHandler -> UUID -> [ClientID] -> Builder -> IO () sendReply handler uuid clientIds replyBuilder = do -- Build the response. let response = mkResponse uuid clientIds replyBuilder -- Send the response. ZMQ.send (chPublishSocket handler) response []