warp 0.3.0 → 0.3.1
raw patch · 2 files changed
+60/−15 lines, 2 files
Files
- Network/Wai/Handler/Warp.hs +57/−14
- warp.cabal +3/−1
Network/Wai/Handler/Warp.hs view
@@ -4,7 +4,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE BangPatterns #-} ------------------------------------------------------------ |+-- -- Module : Network.Wai.Handler.Warp -- Copyright : Michael Snoyman -- License : BSD3@@ -16,14 +16,26 @@ -- A fast, light-weight HTTP server handler for WAI. -- ---------------------------------------------------------++-- | A fast, light-weight HTTP server handler for WAI. Some random notes (a FAQ, if you will):+--+-- * When a 'ResponseFile' indicates a file which does not exist, an exception+-- is thrown. This will close the connection to the client as well. You should+-- handle file existance checks at the application level. module Network.Wai.Handler.Warp- ( run+ ( -- * Run a Warp server+ run+ , runEx+ , serveConnections+ -- * Datatypes+ , Port+ , InvalidRequest (..)+ -- * Utility functions for other packages , sendResponse , parseRequest #if TEST , takeLineMax , takeHeaders- , InvalidRequest (..) #endif ) where @@ -68,30 +80,61 @@ import Data.Word (Word8) import Data.List (foldl') +#if WINDOWS+import Control.Concurrent (threadDelay)+import qualified Control.Concurrent.MVar as MV+import Control.Monad (forever)+#endif++-- | Run an 'Application' on the given port, ignoring all exceptions. run :: Port -> Application -> IO ()-run port = withSocketsDo . -- FIXME should this be called by client user instead?+run = runEx (const $ return ())++-- | Run an 'Application' on the given port, with the given exception handler.+-- Please note that you will also receive 'InvalidRequest' exceptions.+runEx :: (SomeException -> IO ()) -> Port -> Application -> IO ()+#if WINDOWS+runEx onE port app = withSocketsDo $ do+ var <- MV.newMVar Nothing+ let clean = MV.modifyMVar_ var $ \s -> maybe (return ()) sClose s >> return Nothing+ _ <- forkIO $ bracket+ (listenOn $ PortNumber $ fromIntegral port)+ (const clean)+ (\s -> do+ MV.modifyMVar_ var (\_ -> return $ Just s)+ serveConnections onE port app s)+ forever (threadDelay maxBound) `finally` clean+#else+runEx onE port = withSocketsDo . -- FIXME should this be called by client user instead? bracket (listenOn $ PortNumber $ fromIntegral port) sClose .- serveConnections port+ serveConnections onE port+#endif+ type Port = Int -serveConnections :: Port -> Application -> Socket -> IO ()-serveConnections port app socket = do+-- | Runs a server, listening on the given socket. The user is responsible for+-- closing the socket after 'runWithSocket' completes. You must also supply a+-- 'Port' argument for use in the 'serverPort' record; however, this field is+-- only used for informational purposes. If you are in fact listening on a+-- non-TCP socket, this can be a ficticious value.+serveConnections :: (SomeException -> IO ())+ -> Port -> Application -> Socket -> IO ()+serveConnections onE port app socket = do (conn, sa) <- accept socket- _ <- forkIO $ serveConnection port app conn sa- serveConnections port app socket+ _ <- forkIO $ serveConnection onE port app conn sa+ serveConnections onE port app socket -serveConnection :: Port -> Application -> Socket -> SockAddr -> IO ()-serveConnection port app conn remoteHost' = do+serveConnection :: (SomeException -> IO ())+ -> Port -> Application -> Socket -> SockAddr -> IO ()+serveConnection onException port app conn remoteHost' = do catch (finally (E.run_ $ fromClient $$ serveConnection') (sClose conn))- ignoreAll+ onException where- ignoreAll :: SomeException -> IO ()- ignoreAll _ = return () fromClient = enumSocket bytesPerRead conn serveConnection' = do (enumeratee, env) <- parseRequest port remoteHost'
warp.cabal view
@@ -1,5 +1,5 @@ Name: warp-Version: 0.3.0+Version: 0.3.1 Synopsis: A fast, light-weight web server for WAI applications. License: BSD3 License-file: LICENSE@@ -35,6 +35,8 @@ ghc-options: -Wall if !flag(timeout-protection) Cpp-options: -DNO_TIMEOUT_PROTECTION+ if os(windows)+ Cpp-options: -DWINDOWS source-repository head type: git