mongrel2-handler 0.1.0 → 0.1.1
raw patch · 3 files changed
+77/−4 lines, 3 files
Files
- mongrel2-handler.cabal +3/−2
- src/Mongrel2.hs +72/−0
- src/Mongrel2/Parser.hs +2/−2
mongrel2-handler.cabal view
@@ -1,5 +1,5 @@ Name: mongrel2-handler-Version: 0.1.0+Version: 0.1.1 Synopsis: Mongrel2 Handler Library Description: Mongrel2 Handler Library. License: MIT@@ -25,6 +25,7 @@ Extensions: OverloadedStrings Ghc-options: -Wall -fno-warn-unused-matches Hs-source-dirs: src- Exposed-modules: Mongrel2.Parser+ Exposed-modules: Mongrel2+ Mongrel2.Parser Mongrel2.Response Mongrel2.Types
+ src/Mongrel2.hs view
@@ -0,0 +1,72 @@+module Mongrel2+ ( Handler+ , ConnectedHandler+ , mkHandler+ , withConnectedHandler+ , receiveRequest+ , sendReply+ -- Re-exported+ , Message+ , UUID+ , ClientID+ ) where++import Blaze.ByteString.Builder (Builder)+import Data.Attoparsec+import Mongrel2.Parser (messageParser, Message, 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 Message+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 []
src/Mongrel2/Parser.hs view
@@ -76,5 +76,5 @@ extractQuery (Object hdrs) = case M.lookup "URI" hdrs of Just (String uriText) -> decodePath $ encodeUtf8 uriText- _ -> error "Missing/invalid 'URI' in headers received from Mongrel2"-extractQuery _ = error "Invalid headers received from Mongrel2"+ _ -> fail "Missing/invalid 'URI' in headers received from Mongrel2"+extractQuery _ = fail "Invalid headers received from Mongrel2"