packages feed

warp 0.3.2.2 → 0.3.2.3

raw patch · 2 files changed

+28/−39 lines, 2 files

Files

Network/Wai/Handler/Warp.hs view
@@ -64,6 +64,7 @@     , fromException     ) import Control.Concurrent (forkIO, threadWaitWrite)+import qualified Data.Char as C import Data.Maybe (fromMaybe)  import Data.Typeable (Typeable)@@ -206,19 +207,18 @@ parseRequest' _ [] _ = E.throwError $ NotEnoughLines [] parseRequest' port (firstLine:otherLines) remoteHost' = do     (method, rpath', gets, httpversion) <- parseFirst firstLine-    let rpath =+    let (host',rpath) =             if S.null rpath'-                then "/"-                else rpath'+                then ("","/")+                else if "http://" `S.isPrefixOf` rpath'+                         then S.breakByte 47 $ S.drop 7 rpath' -- '/'+                         else ("", rpath')     let heads = map parseHeaderNoAttr otherLines-    let host = fromMaybe "" $ lookup "host" heads+    let host = fromMaybe host' $ lookup "host" heads     let len =             case lookup "content-length" heads of                 Nothing -> 0-                Just bs ->-                    case reads $ B.unpack bs of -- FIXME could probably be optimized-                        (x, _):_ -> x-                        [] -> 0+                Just bs -> fromIntegral $ B.foldl' (\i c -> i * 10 + C.digitToInt c) 0 $ B.takeWhile C.isDigit bs     let serverName' = takeUntil 58 host -- ':'     -- FIXME isolate takes an Integer instead of Int or Int64. If this is a     -- performance penalty, we may need our own version.@@ -245,18 +245,15 @@  parseFirst :: ByteString            -> E.Iteratee S.ByteString IO (ByteString, ByteString, ByteString, HttpVersion)-parseFirst s = do-    let pieces = S.split 32 s  -- ' '-    (method, query, http') <--        case pieces of-            [x, y, z] -> return (x, y, z)-            _ -> E.throwError $ BadFirstLine $ B.unpack s-    let (hfirst, hsecond) = B.splitAt 5 http'-    if (hfirst == "HTTP/")-        then-            let (rpath, qstring) = B.break (== '?') query-             in return (method, rpath, qstring, hsecond)-        else E.throwError NonHttp+parseFirst s = +    case S.split 32 s of  -- ' '+        [method, query, http'] -> do+            let (hfirst, hsecond) = B.splitAt 5 http'+            if hfirst == "HTTP/"+               then let (rpath, qstring) = S.breakByte 63 query  -- '?'+                    in return (method, rpath, qstring, hsecond)+               else E.throwError NonHttp+        _ -> E.throwError $ BadFirstLine $ B.unpack s {-# INLINE parseFirst #-} -- FIXME is this inline necessary? the function is only called from one place and not exported  httpBuilder, spaceBuilder, newlineBuilder, transferEncodingBuilder@@ -329,8 +326,7 @@         return True   where     headers' = headers hv s hs isChunked'-    b' =-        if isChunked'+    b' = if isChunked'             then headers'                  `mappend` chunkedTransferEncoding b                  `mappend` chunkedTransferTerminator@@ -342,14 +338,12 @@     res go   where     -- FIXME perhaps alloca a buffer per thread and reuse that in all functiosn below. Should lessen greatly the GC burden (I hope)-    go s hs-        | not (hasBody s req) = do+    go s hs | not (hasBody s req) = do             liftIO $ Sock.sendMany socket                    $ L.toChunks $ toLazyByteString                    $ headers hv s hs False             return True-    go s hs =-            chunk'+    go s hs = chunk'           $ E.enumList 1 [headers hv s hs isChunked']          $$ E.joinI $ builderToByteString -- FIXME unsafeBuilderToByteString          $$ (iterSocket th socket >> return isKeepAlive)@@ -357,10 +351,9 @@         hasLength = lookup "content-length" hs /= Nothing         isChunked' = isChunked hv && not hasLength         isKeepAlive = isChunked' || hasLength-        chunk' i =-            if isChunked'-                then E.joinI $ chunk $$ i-                else i+        chunk' i = if isChunked'+                      then E.joinI $ chunk $$ i+                      else i         chunk :: E.Enumeratee Builder Builder IO Bool         chunk = E.checkDone $ E.continue . step         step k E.EOF = k (E.Chunks [chunkedTransferTerminator]) >>== return@@ -374,8 +367,8 @@         restLen = S.length rest         -- FIXME check for colon without following space?         rest' = if restLen > 1 && SU.unsafeTake 2 rest == ": "-                    then SU.unsafeDrop 2 rest-                    else rest+                   then SU.unsafeDrop 2 rest+                   else rest      in (mkCIByteString k, rest')  enumSocket :: T.Handle -> Int -> Socket -> E.Enumerator ByteString IO a@@ -386,13 +379,9 @@         bs <- liftIO $ Sock.recv socket len         liftIO $ T.tickle th         if S.null bs-            then E.throwError SocketTimeout-            else go k bs+            then E.continue k+            else k (E.Chunks [bs]) >>== inner     inner step = E.returnI step-    go k bs-        | S.length bs == 0 = E.continue k-        | otherwise = k (E.Chunks [bs]) >>== enumSocket th len socket- ------ The functions below are not warp-specific and could be split out into a --separate package. 
warp.cabal view
@@ -1,5 +1,5 @@ Name:                warp-Version:             0.3.2.2+Version:             0.3.2.3 Synopsis:            A fast, light-weight web server for WAI applications. License:             BSD3 License-file:        LICENSE