@@ -22,13 +22,13 @@ import Control.Monad (when)
22import Data.ByteString.Builder (byteString)
22import Data.ByteString.Builder (byteString)
23import qualified Network.HTTP.Types as H
23import qualified Network.HTTP.Types as H
24import Network.HTTP2
24import Network.HTTP2
25import Network.Wai
26import Network.Wai
26−import Network.Wai.Handler.Warp.File
27import Network.Wai.Handler.Warp.FileInfoCache
27import Network.Wai.Handler.Warp.FileInfoCache
28import Network.Wai.Handler.Warp.HTTP2.EncodeFrame
28import Network.Wai.Handler.Warp.HTTP2.EncodeFrame
29+import Network.Wai.Handler.Warp.HTTP2.File
29import Network.Wai.Handler.Warp.HTTP2.Manager
30import Network.Wai.Handler.Warp.HTTP2.Manager
30import Network.Wai.Handler.Warp.HTTP2.Types
31import Network.Wai.Handler.Warp.HTTP2.Types
31−import Network.Wai.Handler.Warp.Header
32import Network.Wai.Handler.Warp.IORef
32import Network.Wai.Handler.Warp.IORef
33import qualified Network.Wai.Handler.Warp.Response as R
33import qualified Network.Wai.Handler.Warp.Response as R
34import qualified Network.Wai.Handler.Warp.Settings as S
34import qualified Network.Wai.Handler.Warp.Settings as S
@@ -41,14 +41,15 @@ import Network.Wai.Internal (Response(..), ResponseReceived(..), ResponseReceive
41-- | The wai definition is 'type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived'.
41-- | The wai definition is 'type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived'.
42-- This type implements the second argument (Response -> IO ResponseReceived)
42-- This type implements the second argument (Response -> IO ResponseReceived)
43-- with extra arguments.
43-- with extra arguments.
44+type Responder = InternalInfo -> ValueTable ->
44−type Responder = InternalInfo -> ThreadContinue -> Stream -> Request ->
45+ ThreadContinue -> Stream -> Request ->
45 Response -> IO ResponseReceived
46 Response -> IO ResponseReceived
47-- | This function is passed to workers.
48-- | This function is passed to workers.
48-- They also pass 'Response's from 'Application's to this function.
49-- They also pass 'Response's from 'Application's to this function.
49-- This function enqueues commands for the HTTP/2 sender.
50-- This function enqueues commands for the HTTP/2 sender.
50response :: S.Settings -> Context -> Manager -> Responder
51response :: S.Settings -> Context -> Manager -> Responder
51−response settings Context{outputQ} mgr ii tconf strm req rsp = case rsp of
52+response settings Context{outputQ} mgr ii reqvt tconf strm req rsp = case rsp of
52 ResponseStream s0 hs0 strmbdy
53 ResponseStream s0 hs0 strmbdy
53 | noBody s0 -> responseNoBody s0 hs0
54 | noBody s0 -> responseNoBody s0 hs0
54 | isHead -> responseNoBody s0 hs0
55 | isHead -> responseNoBody s0 hs0
@@ -73,18 +74,21 @@ response settings Context{outputQ} mgr ii tconf strm req rsp = case rsp of
73 -- log message are written here even the window size of streams
74 -- log message are written here even the window size of streams
76− responseNoBody s hs = do
77+ responseNoBody s hs0 = toHeaderTable hs0 >>= responseNoBody' s
79+ responseNoBody' s tbl = do
77 logger req s Nothing
80 logger req s Nothing
78 setThreadContinue tconf True
81 setThreadContinue tconf True
79− let rspn = RspnNobody s hs
82+ let rspn = RspnNobody s tbl
80 out = ORspn strm rspn ii
83 out = ORspn strm rspn ii
81 enqueueOutput outputQ out
84 enqueueOutput outputQ out
82 return ResponseReceived
85 return ResponseReceived
84− responseBuilderBody s hs bdy = do
87+ responseBuilderBody s hs0 bdy = do
85 logger req s Nothing
88 logger req s Nothing
86 setThreadContinue tconf True
89 setThreadContinue tconf True
90+ tbl <- toHeaderTable hs0
87− let rspn = RspnBuilder s hs bdy
91+ let rspn = RspnBuilder s tbl bdy
88 out = ORspn strm rspn ii
92 out = ORspn strm rspn ii
89 enqueueOutput outputQ out
93 enqueueOutput outputQ out
90 return ResponseReceived
94 return ResponseReceived
@@ -93,20 +97,24 @@ response settings Context{outputQ} mgr ii tconf strm req rsp = case rsp of
93 efinfo <- E.try $ getFileInfo ii path
97 efinfo <- E.try $ getFileInfo ii path
94 case efinfo of
98 case efinfo of
95 Left (_ex :: E.IOException) -> response404 hs0
99 Left (_ex :: E.IOException) -> response404 hs0
101+ (rspths0,vt) <- toHeaderTable hs0
96− Right finfo -> case conditionalRequest finfo hs0 (indexRequestHeader (requestHeaders req)) of
102+ case conditionalRequest finfo rspths0 reqvt of
97− WithoutBody s -> responseNoBody s hs0
103+ WithoutBody s -> responseNoBody s hs0
98− WithBody s hs beg len -> responseFile2XX s hs path (Just (FilePart beg len (fileInfoSize finfo)))
104+ WithBody s rspths beg len -> responseFile2XX s (rspths,vt) path (Just (FilePart beg len (fileInfoSize finfo)))
100− responseFileXXX s0 hs0 path mpart = responseFile2XX s0 hs0 path mpart
106+ responseFileXXX s0 hs0 path mpart = do
107+ tbl <- toHeaderTable hs0
108+ responseFile2XX s0 tbl path mpart
102− responseFile2XX s hs path mpart
110+ responseFile2XX s tbl path mpart
103 | isHead = do
111 | isHead = do
104 logger req s Nothing
112 logger req s Nothing
105− responseNoBody s hs
113+ responseNoBody' s tbl
106 | otherwise = do
114 | otherwise = do
107 logger req s (filePartByteCount <$> mpart)
115 logger req s (filePartByteCount <$> mpart)
108 setThreadContinue tconf True
116 setThreadContinue tconf True
109− let rspn = RspnFile s hs path mpart
117+ let rspn = RspnFile s tbl path mpart
110 out = ORspn strm rspn ii
118 out = ORspn strm rspn ii
111 enqueueOutput outputQ out
119 enqueueOutput outputQ out
112 return ResponseReceived
120 return ResponseReceived
@@ -131,7 +139,8 @@ response settings Context{outputQ} mgr ii tconf strm req rsp = case rsp of
131 -- Since 'StreamingBody' is loop, we cannot control it.
139 -- Since 'StreamingBody' is loop, we cannot control it.
132 -- So, let's serialize 'Builder' with a designated queue.
140 -- So, let's serialize 'Builder' with a designated queue.
133 tbq <- newTBQueueIO 10 -- fixme: hard coding: 10
141 tbq <- newTBQueueIO 10 -- fixme: hard coding: 10
142+ tbl <- toHeaderTable hs0
134− let rspn = RspnStreaming s0 hs0 tbq
143+ let rspn = RspnStreaming s0 tbl tbq
135 out = ORspn strm rspn ii
144 out = ORspn strm rspn ii
136 enqueueOutput outputQ out
145 enqueueOutput outputQ out
137 let push b = do
146 let push b = do
@@ -153,11 +162,11 @@ worker ctx@Context{inputQ,controlQ} set app responder tm = do
153 setThreadContinue tcont True
162 setThreadContinue tcont True
154 ex <- E.try $ do
163 ex <- E.try $ do
155 T.pause th
164 T.pause th
156− inp@(Input strm req ii) <- atomically $ readTQueue inputQ
165+ inp@(Input strm req reqvt ii) <- atomically $ readTQueue inputQ
157 setStreamInfo sinfo inp
166 setStreamInfo sinfo inp
158 T.resume th
167 T.resume th
159 T.tickle th
168 T.tickle th
160− app req $ responder ii tcont strm req
169+ app req $ responder ii reqvt tcont strm req
161 cont1 <- case ex of
170 cont1 <- case ex of
162 Right ResponseReceived -> return True
171 Right ResponseReceived -> return True
163 Left e@(SomeException _)
172 Left e@(SomeException _)
@@ -177,7 +186,7 @@ worker ctx@Context{inputQ,controlQ} set app responder tm = do
177 minp <- getStreamInfo sinfo
186 minp <- getStreamInfo sinfo
178 case minp of
187 case minp of
179 Nothing -> return ()
188 Nothing -> return ()
180− Just (Input strm req _ii) -> do
189+ Just (Input strm req _reqvt _ii) -> do
181 closed ctx strm Killed
190 closed ctx strm Killed
182 let frame = resetFrame InternalError (streamNumber strm)
191 let frame = resetFrame InternalError (streamNumber strm)
183 enqueueControl controlQ $ CFrame frame
192 enqueueControl controlQ $ CFrame frame
@@ -196,12 +205,15 @@ worker ctx@Context{inputQ,controlQ} set app responder tm = do
196-- Otherwise, the worker get finished.
205-- Otherwise, the worker get finished.
197newtype ThreadContinue = ThreadContinue (IORef Bool)
206newtype ThreadContinue = ThreadContinue (IORef Bool)
208+{-# INLINE newThreadContinue #-}
199newThreadContinue :: IO ThreadContinue
209newThreadContinue :: IO ThreadContinue
200newThreadContinue = ThreadContinue <$> newIORef True
210newThreadContinue = ThreadContinue <$> newIORef True
212+{-# INLINE setThreadContinue #-}
202setThreadContinue :: ThreadContinue -> Bool -> IO ()
213setThreadContinue :: ThreadContinue -> Bool -> IO ()
203setThreadContinue (ThreadContinue ref) x = writeIORef ref x
214setThreadContinue (ThreadContinue ref) x = writeIORef ref x
216+{-# INLINE getThreadContinue #-}
205getThreadContinue :: ThreadContinue -> IO Bool
217getThreadContinue :: ThreadContinue -> IO Bool
206getThreadContinue (ThreadContinue ref) = readIORef ref
218getThreadContinue (ThreadContinue ref) = readIORef ref
@@ -210,14 +222,18 @@ getThreadContinue (ThreadContinue ref) = readIORef ref
210-- | The type to store enough information for 'settingsOnException'.
222-- | The type to store enough information for 'settingsOnException'.
211newtype StreamInfo = StreamInfo (IORef (Maybe Input))
223newtype StreamInfo = StreamInfo (IORef (Maybe Input))
225+{-# INLINE newStreamInfo #-}
213newStreamInfo :: IO StreamInfo
226newStreamInfo :: IO StreamInfo
214newStreamInfo = StreamInfo <$> newIORef Nothing
227newStreamInfo = StreamInfo <$> newIORef Nothing
229+{-# INLINE clearStreamInfo #-}
216clearStreamInfo :: StreamInfo -> IO ()
230clearStreamInfo :: StreamInfo -> IO ()
217clearStreamInfo (StreamInfo ref) = writeIORef ref Nothing
231clearStreamInfo (StreamInfo ref) = writeIORef ref Nothing
233+{-# INLINE setStreamInfo #-}
219setStreamInfo :: StreamInfo -> Input -> IO ()
234setStreamInfo :: StreamInfo -> Input -> IO ()
220setStreamInfo (StreamInfo ref) inp = writeIORef ref $ Just inp
235setStreamInfo (StreamInfo ref) inp = writeIORef ref $ Just inp
237+{-# INLINE getStreamInfo #-}
222getStreamInfo :: StreamInfo -> IO (Maybe Input)
238getStreamInfo :: StreamInfo -> IO (Maybe Input)
223getStreamInfo (StreamInfo ref) = readIORef ref
239getStreamInfo (StreamInfo ref) = readIORef ref