packages feed

mongrel2-handler 0.1.0 → 0.1.1

raw patch · 3 files changed

+77/−4 lines, 3 files

Files

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"