@@ -29,7 +29,7 @@ import Control.Exception (bracket, finally, Exception)
29import System.IO (Handle, hClose)
29import System.IO (Handle, hClose)
30import Control.Concurrent
30import Control.Concurrent
31import Control.Monad (unless)
31import Control.Monad (unless)
32−import Data.Maybe (isJust, fromJust)
32+import Data.Maybe (isJust, fromJust, fromMaybe)
34import Control.Failure
34import Control.Failure
35import Data.Typeable (Typeable)
35import Data.Typeable (Typeable)
@@ -37,6 +37,8 @@ import Data.Typeable (Typeable)
37import Web.Encodings.StringLike (StringLike)
37import Web.Encodings.StringLike (StringLike)
38import qualified Web.Encodings.StringLike as SL
38import qualified Web.Encodings.StringLike as SL
40run :: Port -> Application -> IO ()
42run :: Port -> Application -> IO ()
41run port = withSocketsDo .
43run port = withSocketsDo .
@@ -97,12 +99,11 @@ data InvalidRequest =
97instance Exception InvalidRequest
99instance Exception InvalidRequest
99-- | Parse a set of header lines and body into a 'Request'.
101-- | Parse a set of header lines and body into a 'Request'.
100−parseRequest :: (MonadFailure InvalidRequest m)
102+parseRequest :: Port
102− -> [BS.ByteString]
103+ -> [BS.ByteString]
103− -> Handle
104+ -> Handle
104− -> String
105+ -> String
105− -> m Request
106+ -> IO Request
106parseRequest port lines' handle remoteHost' = do
107parseRequest port lines' handle remoteHost' = do
107 case lines' of
108 case lines' of
108 (_:_:_) -> return ()
109 (_:_:_) -> return ()
@@ -116,10 +117,11 @@ parseRequest port lines' handle remoteHost' = do
116 let host' = lookup (SL.pack "Host") heads
117 let host' = lookup (SL.pack "Host") heads
117 unless (isJust host') $ failure HostNotIncluded
118 unless (isJust host') $ failure HostNotIncluded
118 let host = fromJust host'
119 let host = fromJust host'
119− {- FIXME use length somewhere?
120+ let len = fromMaybe 0 $ do
120− let len = maybe "0" SL.unpack
121− $ lookup (SL.pack "Content-Length") heads
121+ bs <- lookup (SL.pack "Content-Length") heads
122− -}
122+ let str = SL.unpack bs
123 let (serverName', _) = SL.breakChar ':' host
125 let (serverName', _) = SL.breakChar ':' host
124 return $ Request
126 return $ Request
125 { requestMethod = method
127 { requestMethod = method
@@ -129,18 +131,19 @@ parseRequest port lines' handle remoteHost' = do
129 , serverPort = port
131 , serverPort = port
130 , httpHeaders = heads
132 , httpHeaders = heads
131 , urlScheme = HTTP
133 , urlScheme = HTTP
132− , requestBody = RequestBody $ SSRequestBody handle
134+ , requestBody = requestBodyHandle handle mlen
133 , errorHandler = System.IO.hPutStr System.IO.stderr
135 , errorHandler = System.IO.hPutStr System.IO.stderr
134 , remoteHost = remoteHost'
136 , remoteHost = remoteHost'
137−newtype SSRequestBody = SSRequestBody Handle
139+requestBodyHandle :: Handle -> MVar Int -> IO (Maybe BS.ByteString)
138−instance RequestBodyClass SSRequestBody where
140+requestBodyHandle h mlen = modifyMVar mlen helper where
139− receiveByteString (SSRequestBody h) = do
141+ helper :: Int -> IO (Int, Maybe BS.ByteString)
140− bs <- BS.hGet h 1024 -- FIXME find a good chunk size
142+ helper 0 = return (0, Nothing)
141− if BS.null bs
143+ helper len = do
142− then return Nothing
144+ bs <- BS.hGet h len
145+ let newLen = len - BS.length bs
143− else return $ Just bs
146+ return (newLen, Just bs)
145parseFirst :: (StringLike s, MonadFailure InvalidRequest m) =>
148parseFirst :: (StringLike s, MonadFailure InvalidRequest m) =>