on master help sign in
introducing indexed header.
commitba3e2eba38067a783f81756644d230553df6faf6 authorKazu Yamamoto <kazu@iij.ad.jp> dateTue 29 Oct 2013, 17:17 (13 years ago) parent65e17d6
5 files changed+92−29
warp/Network/Wai/Handler/Warp/Header.hs+52 warp/Network/Wai/Handler/Warp/Request.hs+31−25 warp/Network/Wai/Handler/Warp/RequestHeader.hs+1−1 warp/Network/Wai/Handler/Warp/Types.hs+5−3 warp/warp.cabal+3
warp/Network/Wai/Handler/Warp/Header.hsnew file+52
@@ -0,0 +1,52 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+
3+module Network.Wai.Handler.Warp.Header where
4+
5+import Data.Array
6+import Data.Array.ST
7+import Network.HTTP.Types
8+import Network.Wai.Handler.Warp.Types
9+
10+----------------------------------------------------------------
11+
12+type IndexedHeader = Array Int (Maybe HeaderValue)
13+
14+----------------------------------------------------------------
15+
16+indexRequestHeader :: RequestHeaders -> IndexedHeader
17+indexRequestHeader hdr = traverseHeader hdr requestMaxIndex
18+
19+idxContentLength,idxTransferEncoding,idxExpect :: Int
20+idxConnection,idxRange,idxHost :: Int
21+idxContentLength = 0
22+idxTransferEncoding = 1
23+idxExpect = 2
24+idxConnection = 3
25+idxRange = 4
26+idxHost = 5
27+
28+requestMaxIndex :: Int
29+requestMaxIndex = 5
30+
31+----------------------------------------------------------------
32+
33+traverseHeader :: [Header] -> Int -> IndexedHeader
34+traverseHeader hdr maxidx = runSTArray $ do
35+ arr <- newArray (0,maxidx) Nothing
36+ mapM_ (insert arr) hdr
37+ return arr
38+ where
39+ insert arr (key,val)
40+ | idx == -1 = return ()
41+ | otherwise = writeArray arr idx (Just val)
42+ where
43+ idx = keyIndex key
44+
45+keyIndex :: HeaderName -> Int
46+keyIndex "content-length" = idxContentLength
47+keyIndex "transfer-encoding" = idxTransferEncoding
48+keyIndex "expect" = idxExpect
49+keyIndex "connection" = idxConnection
50+keyIndex "range" = idxRange
51+keyIndex "host" = idxHost
52+keyIndex _ = -1
warp/Network/Wai/Handler/Warp/Request.hs+31−25
@@ -10,6 +10,7 @@ module Network.Wai.Handler.Warp.Request (
1010import Control.Applicative
1111import Control.Exception.Lifted (throwIO)
1212import Control.Monad.IO.Class (liftIO)
13+import Data.Array ((!))
1314import Data.ByteString (ByteString)
1415import qualified Data.ByteString as S
1516import qualified Data.ByteString.Unsafe as SU
@@ -21,6 +22,7 @@ import qualified Network.HTTP.Types as H
2122import Network.Socket (SockAddr)
2223import Network.Wai
2324import Network.Wai.Handler.Warp.Conduit
25+import Network.Wai.Handler.Warp.Header
2426import Network.Wai.Handler.Warp.ReadInt
2527import Network.Wai.Handler.Warp.RequestHeader
2628import qualified Network.Wai.Handler.Warp.Timeout as Timeout
@@ -43,9 +45,12 @@ recvRequest :: Connection
4345 -> IO (Request, IO (ResumableSource IO ByteString))
4446recvRequest conn timeoutHandle remoteHost' src0 = do
4547 (src, hdrlines) <- src0 $$+ headerLines
46− (method, rpath, gets, httpversion, hdr') <- parseHeaderLines hdrlines
47− hdr <- liftIO $ handleExpect conn httpversion id hdr'
48− (rbody, bodyLength, getSource) <- bodyAndSource src hdr
48+ (method, rpath, gets, httpversion, hdr) <- parseHeaderLines hdrlines
49+ let idxhdr = indexRequestHeader hdr
50+ liftIO $ handleExpect conn httpversion (idxhdr ! idxExpect)
51+ (rbody, bodyLength, getSource) <- bodyAndSource src
52+ (idxhdr ! idxContentLength)
53+ (idxhdr ! idxTransferEncoding)
4954
5055 return (Request
5156 { requestMethod = method
@@ -72,41 +77,42 @@ headerLines =
7277
7378handleExpect :: Connection
7479 -> H.HttpVersion
75− -> (H.RequestHeaders -> H.RequestHeaders)
76− -> H.RequestHeaders
77− -> IO H.RequestHeaders
78−handleExpect _ _ front [] = return $ front []
79−handleExpect conn hv front (("expect", "100-continue"):rest) = do
80− connSendAll conn $
81− if hv == H.http11
82− then "HTTP/1.1 100 Continue\r\n\r\n"
83− else "HTTP/1.0 100 Continue\r\n\r\n"
84− return $ front rest
85−handleExpect conn hv front (x:xs) = handleExpect conn hv (front . (x:)) xs
80+ -> Maybe HeaderValue
81+ -> IO ()
82+handleExpect conn ver (Just "100-continue") = connSendAll conn continue
83+ where
84+ continue
85+ | ver == H.http11 = "HTTP/1.1 100 Continue\r\n\r\n"
86+ | otherwise = "HTTP/1.0 100 Continue\r\n\r\n"
87+handleExpect _ _ _ = return ()
8688
8789----------------------------------------------------------------
8890
8991bodyAndSource :: ResumableSource IO ByteString
90− -> H.RequestHeaders
92+ -> Maybe HeaderValue
93+ -> Maybe HeaderValue
9194 -> IO (Source IO ByteString
9295 ,RequestBodyLength
9396 ,IO (ResumableSource IO ByteString))
94−bodyAndSource src hdr
97+bodyAndSource src cl te
9598 | chunked = do
9699 ref <- I.newIORef (src, NeedLen)
97100 return (chunkedSource ref, ChunkedBody, fst <$> I.readIORef ref)
98101 | otherwise = do
99− ibs <- IsolatedBSSource <$> I.newIORef (len0, src)
102+ ibs <- IsolatedBSSource <$> I.newIORef (len, src)
100103 return (ibsIsolate ibs, bodyLen, ibsDone ibs)
101104 where
102− len0 = case lookup H.hContentLength hdr of
103− Nothing -> 0
104− Just bs -> readInt bs
105− bodyLen = KnownLength $ fromIntegral len0
106− chunked = isChunked hdr
107−
108−isChunked :: H.RequestHeaders -> Bool
109−isChunked hdr = maybe False ((== "chunked") . CI.foldCase) $ lookup hTransferEncoding hdr
105+ len = toLength cl
106+ bodyLen = KnownLength $ fromIntegral len
107+ chunked = isChunked te
108+
109+toLength :: Maybe HeaderValue -> Int
110+toLength Nothing = 0
111+toLength (Just bs) = readInt bs
112+
113+isChunked :: Maybe HeaderValue -> Bool
114+isChunked (Just bs) = CI.foldCase bs == "chunked"
115+isChunked _ = False
110116
111117----------------------------------------------------------------
112118
warp/Network/Wai/Handler/Warp/RequestHeader.hs+1−1
@@ -3,7 +3,7 @@
33module Network.Wai.Handler.Warp.RequestHeader (parseHeaderLines) where
44
55import Control.Exception.Lifted (throwIO)
6−import Data.ByteString (ByteString)
6+import Data.ByteString.Char8 (ByteString)
77import qualified Data.ByteString as S
88import qualified Data.ByteString.Char8 as B (unpack)
99import qualified Data.CaseInsensitive as CI
warp/Network/Wai/Handler/Warp/Types.hs+5−3
@@ -8,11 +8,11 @@ import Control.Exception
88import Data.ByteString (ByteString)
99import Data.Typeable (Typeable)
1010import Data.Version (showVersion)
11−import Network.Socket (Socket)
1211import Network.HTTP.Types.Header
13−import qualified Paths_warp
14−import qualified Network.Wai.Handler.Warp.Timeout as T
12+import Network.Socket (Socket)
1513import qualified Network.Wai.Handler.Warp.FdCache as F
14+import qualified Network.Wai.Handler.Warp.Timeout as T
15+import qualified Paths_warp
1616
1717----------------------------------------------------------------
1818
@@ -26,6 +26,8 @@ type Port = Int
2626
2727----------------------------------------------------------------
2828
29+type HeaderValue = ByteString
30+
2931hTransferEncoding :: HeaderName
3032hTransferEncoding = "Transfer-Encoding"
3133
warp/warp.cabal+3
@@ -31,6 +31,7 @@ Flag allow-sendfilefd
3131
3232Library
3333 Build-Depends: base >= 3 && < 5
34+ , array
3435 , blaze-builder >= 0.2.1.4 && < 0.4
3536 , blaze-builder-conduit >= 0.5 && < 1.1
3637 , bytestring >= 0.9.1.4
@@ -55,6 +56,7 @@ Library
5556 Network.Wai.Handler.Warp.Timeout
5657 Other-modules: Network.Wai.Handler.Warp.Conduit
5758 Network.Wai.Handler.Warp.FdCache
59+ Network.Wai.Handler.Warp.Header
5860 Network.Wai.Handler.Warp.ReadInt
5961 Network.Wai.Handler.Warp.Recv
6062 Network.Wai.Handler.Warp.Request
@@ -94,6 +96,7 @@ Test-Suite spec
9496
9597 Ghc-Options: -Wall
9698 Build-Depends: base >= 4 && < 5
99+ , array
97100 , blaze-builder >= 0.2.1.4 && < 0.4
98101 , blaze-builder-conduit >= 0.5
99102 , bytestring >= 0.9.1.4