@@ -12,6 +12,7 @@ import Blaze.ByteString.Builder.HTTP (chunkedTransferEncoding, chunkedTransferTe
12import Control.Applicative
12import Control.Applicative
13import Control.Exception
13import Control.Exception
14import Control.Monad.IO.Class (liftIO)
14import Control.Monad.IO.Class (liftIO)
15+import Data.Array ((!))
15import Data.ByteString (ByteString)
16import Data.ByteString (ByteString)
16import qualified Data.ByteString.Char8 as B (pack)
17import qualified Data.ByteString.Char8 as B (pack)
17import qualified Data.CaseInsensitive as CI
18import qualified Data.CaseInsensitive as CI
@@ -20,17 +21,18 @@ import Data.Conduit.Blaze (builderToByteString)
20import qualified Data.Conduit.List as CL
21import qualified Data.Conduit.List as CL
21import Data.Maybe (isJust, listToMaybe)
22import Data.Maybe (isJust, listToMaybe)
22import Data.Monoid (mappend)
23import Data.Monoid (mappend)
24+import Network.HTTP.Attoparsec (parseByteRanges)
23import qualified Network.HTTP.Types as H
25import qualified Network.HTTP.Types as H
24import Network.Wai
26import Network.Wai
25−import Network.Wai.Internal
27+import Network.Wai.Handler.Warp.Header
26import Network.Wai.Handler.Warp.ReadInt
28import Network.Wai.Handler.Warp.ReadInt
27−import Network.Wai.Handler.Warp.Settings
28import qualified Network.Wai.Handler.Warp.ResponseHeader as RH
29import qualified Network.Wai.Handler.Warp.ResponseHeader as RH
30+import Network.Wai.Handler.Warp.Settings
29import qualified Network.Wai.Handler.Warp.Timeout as T
31import qualified Network.Wai.Handler.Warp.Timeout as T
30import Network.Wai.Handler.Warp.Types
32import Network.Wai.Handler.Warp.Types
31−import qualified System.PosixCompat.Files as P
33+import Network.Wai.Internal
32−import Network.HTTP.Attoparsec (parseByteRanges)
33import Numeric (showInt)
34import Numeric (showInt)
35+import qualified System.PosixCompat.Files as P
35----------------------------------------------------------------
37----------------------------------------------------------------
36----------------------------------------------------------------
38----------------------------------------------------------------
@@ -38,12 +40,13 @@ import Numeric (showInt)
38sendResponse :: Settings
40sendResponse :: Settings
39 -> InternalInfo -> Request -> Connection
41 -> InternalInfo -> Request -> Connection
40 -> (forall a. IO a -> IO a) -- ^ restore masking state
42 -> (forall a. IO a -> IO a) -- ^ restore masking state
41 -> Response
44 -> Response
42 -> IO Bool
45 -> IO Bool
44----------------------------------------------------------------
47----------------------------------------------------------------
46−sendResponse settings ii req conn restore (ResponseFile s0 hs0 path mpart0) =
49+sendResponse settings ii req conn restore reqidxhdr (ResponseFile s0 hs0 path mpart0) =
47 restore $ headerAndLength >>= sendResponse'
50 restore $ headerAndLength >>= sendResponse'
49 hs = addAccept hs0
52 hs = addAccept hs0
@@ -60,14 +63,13 @@ sendResponse settings ii req conn restore (ResponseFile s0 hs0 path mpart0) =
60 let (s, addRange, beg, end) =
63 let (s, addRange, beg, end) =
61 case mpart0 of
64 case mpart0 of
62 Just part -> (s0, id, filePartOffset part, filePartByteCount part)
65 Just part -> (s0, id, filePartOffset part, filePartByteCount part)
64− case lookup H.hRange (requestHeaders req) >>= parseByteRanges >>= listToMaybe of
66+ Nothing -> case reqidxhdr ! idxRange >>= parseByteRanges >>= listToMaybe of
65− Just range | s0 == H.status200 ->
67+ Just range | s0 == H.status200 ->
66− case range of
68+ case range of
67− H.ByteRangeFrom from -> rangeRes cl from (cl - 1)
69+ H.ByteRangeFrom from -> rangeRes cl from (cl - 1)
68− H.ByteRangeFromTo from to -> rangeRes cl from to
70+ H.ByteRangeFromTo from to -> rangeRes cl from to
69− H.ByteRangeSuffix count -> rangeRes cl (cl - count) (cl - 1)
71+ H.ByteRangeSuffix count -> rangeRes cl (cl - count) (cl - 1)
70− _ -> (s0, id, 0, cl)
72+ _ -> (s0, id, 0, cl)
72 | hadLength = hs
74 | hadLength = hs
73 | otherwise = addLength end hs
75 | otherwise = addLength end hs
@@ -95,16 +97,16 @@ sendResponse settings ii req conn restore (ResponseFile s0 hs0 path mpart0) =
95 return isPersist -- FIXME isKeepAlive?
97 return isPersist -- FIXME isKeepAlive?
97 version = httpVersion req
99 version = httpVersion req
98− (isPersist,_) = infoFromRequest req
100+ (isPersist,_) = infoFromRequest req reqidxhdr
100 sendResponse' (Left (_ :: SomeException)) =
102 sendResponse' (Left (_ :: SomeException)) =
101− sendResponse settings ii req conn restore notFound
103+ sendResponse settings ii req conn restore reqidxhdr notFound
103 notFound = responseLBS H.status404 [(H.hContentType, "text/plain")] "File not found"
105 notFound = responseLBS H.status404 [(H.hContentType, "text/plain")] "File not found"
105----------------------------------------------------------------
107----------------------------------------------------------------
107−sendResponse settings ii req conn restore (ResponseBuilder s hs b)
109+sendResponse settings ii req conn restore reqidxhdr (ResponseBuilder s hs b)
108 | hasBody s req = restore $ do
110 | hasBody s req = restore $ do
109 header <- composeHeaderBuilder settings version s hs needsChunked
111 header <- composeHeaderBuilder settings version s hs needsChunked
@@ -122,12 +124,12 @@ sendResponse settings ii req conn restore (ResponseBuilder s hs b)
123 th = threadHandle ii
125 th = threadHandle ii
124 version = httpVersion req
126 version = httpVersion req
125− reqinfo@(isPersist,_) = infoFromRequest req
127+ reqinfo@(isPersist,_) = infoFromRequest req reqidxhdr
126 (isKeepAlive, needsChunked) = infoFromResponse hs reqinfo
128 (isKeepAlive, needsChunked) = infoFromResponse hs reqinfo
128----------------------------------------------------------------
130----------------------------------------------------------------
130−sendResponse settings ii req conn restore (ResponseSource s hs withBodyFlush)
132+sendResponse settings ii req conn restore reqidxhdr (ResponseSource s hs withBodyFlush)
131 | hasBody s req = withBodyFlush $ \bodyFlush -> restore $ do
133 | hasBody s req = withBodyFlush $ \bodyFlush -> restore $ do
132 header <- liftIO $ composeHeaderBuilder settings version s hs needsChunked
134 header <- liftIO $ composeHeaderBuilder settings version s hs needsChunked
133 let src = CL.sourceList [header] `mappend` cbody bodyFlush
135 let src = CL.sourceList [header] `mappend` cbody bodyFlush
@@ -152,7 +154,7 @@ sendResponse settings ii req conn restore (ResponseSource s hs withBodyFlush)
152 chunk :: Conduit Builder IO Builder
154 chunk :: Conduit Builder IO Builder
153 chunk = await >>= maybe (yield chunkedTransferTerminator) (\x -> yield (chunkedTransferEncoding x) >> chunk)
155 chunk = await >>= maybe (yield chunkedTransferTerminator) (\x -> yield (chunkedTransferEncoding x) >> chunk)
154 version = httpVersion req
156 version = httpVersion req
155− reqinfo@(isPersist,_) = infoFromRequest req
157+ reqinfo@(isPersist,_) = infoFromRequest req reqidxhdr
156 (isKeepAlive, needsChunked) = infoFromResponse hs reqinfo
158 (isKeepAlive, needsChunked) = infoFromResponse hs reqinfo
158----------------------------------------------------------------
160----------------------------------------------------------------
@@ -177,16 +179,16 @@ connSink Connection { connSendAll = send } th =
178----------------------------------------------------------------
180----------------------------------------------------------------
180−infoFromRequest :: Request -> (Bool,Bool)
182+infoFromRequest :: Request -> IndexedHeader -> (Bool,Bool)
181−infoFromRequest req = (checkPersist req, checkChunk req)
183+infoFromRequest req reqidxhdr = (checkPersist req reqidxhdr, checkChunk req)
183−checkPersist :: Request -> Bool
185+checkPersist :: Request -> IndexedHeader -> Bool
184−checkPersist req
186+checkPersist req reqidxhdr
185 | ver == H.http11 = checkPersist11 conn
187 | ver == H.http11 = checkPersist11 conn
186 | otherwise = checkPersist10 conn
188 | otherwise = checkPersist10 conn
188 ver = httpVersion req
190 ver = httpVersion req
189− conn = lookup H.hConnection $ requestHeaders req
191+ conn = reqidxhdr ! idxConnection
190 checkPersist11 (Just x)
192 checkPersist11 (Just x)
191 | CI.foldCase x == "close" = False
193 | CI.foldCase x == "close" = False
192 checkPersist11 _ = True
194 checkPersist11 _ = True