on master help sign in
Cleanup: send trailers directly rather than re-enqueuing them.
ec035d4Andrew Pritchard
warp/Network/Wai/Handler/Warp/HTTP2/Sender.hs+24−27
@@ -134,27 +134,6 @@ frameSender ctx@Context{outputQ,connectionWindow}
134 sendResponse strm s h aux lim
134 sendResponse strm s h aux lim
135 putMVar mvar pushed
135 putMVar mvar pushed
136 loop
136 loop
137− switch (OTrailers strm trailers) = do
138− _ <- unlessClosed conn strm $ do
139− -- Trailers always indicate the end of a stream; send them in
140− -- consecutive header+continuation frames and end the stream. Some
141− -- clients dislike empty headers frames, so end the stream with an
142− -- empty data frame instead, as recommended by the spec.
143− toFlush <- case trailers of
144− [] -> frameHeaderLength <$ fillFrameHeader FrameData 0
145− (streamNumber strm)
146− (setEndStream defaultFlags)
147− connWriteBuffer
148− _ -> do
149− builder <- hpackEncodeCIHeaders ctx trailers
150− off <- headerContinue (streamNumber strm) builder True
151− return (off + frameHeaderLength)
152− -- 'closed' must be before 'flushN'. If not, the context would be
153− -- switched to the receiver, resulting in the inconsistency of
154− -- concurrency.
155− closed strm Finished
156− flushN toFlush
157− loop
158
137
159 -- Send the response headers and as much of the response as is immediately
138 -- Send the response headers and as much of the response as is immediately
160 -- available; shared by normal responses and pushed streams.
139 -- available; shared by normal responses and pushed streams.
@@ -177,6 +156,27 @@ frameSender ctx@Context{outputQ,connectionWindow}
177 when needSend $ flushN off
156 when needSend $ flushN off
178 dispatchNext strm mnext
157 dispatchNext strm mnext
179
158
159+ -- Send the stream's trailers and close the stream.
160+ sendTrailers :: Stream -> Trailers -> IO ()
161+ sendTrailers strm trailers = do
162+ -- Trailers always indicate the end of a stream; send them in
163+ -- consecutive header+continuation frames and end the stream. Some
164+ -- clients dislike empty headers frames, so end the stream with an
165+ -- empty data frame instead, as recommended by the spec.
166+ toFlush <- case trailers of
167+ [] -> frameHeaderLength <$ fillFrameHeader FrameData 0
168+ (streamNumber strm)
169+ (setEndStream defaultFlags)
170+ connWriteBuffer
171+ _ -> do
172+ builder <- hpackEncodeCIHeaders ctx trailers
173+ off <- headerContinue (streamNumber strm) builder True
174+ return (off + frameHeaderLength)
175+ -- 'closed' must be before 'flushN'. If not, the context would be
176+ -- switched to the receiver, resulting in the inconsistency of
177+ -- concurrency.
178+ closed strm Finished
179+ flushN toFlush
180
180
181 -- Flush the connection buffer to the socket, where the first 'n' bytes of
181 -- Flush the connection buffer to the socket, where the first 'n' bytes of
182 -- the buffer are filled.
182 -- the buffer are filled.
@@ -237,14 +237,11 @@ frameSender ctx@Context{outputQ,connectionWindow}
237 -- This is done after sending any part of the stream body, so it's shared
237 -- This is done after sending any part of the stream body, so it's shared
238 -- by 'sendResponse' and @switch (ONext ...)@.
238 -- by 'sendResponse' and @switch (ONext ...)@.
239 dispatchNext :: Stream -> Control DynaNext -> IO ()
239 dispatchNext :: Stream -> Control DynaNext -> IO ()
240+ dispatchNext _ CNone = return ()
241+ dispatchNext strm (CFinish trailers) = sendTrailers strm trailers
240− dispatchNext strm (CNext next) = do
242+ dispatchNext strm (CNext next) = do
241 let out = ONext strm next
243 let out = ONext strm next
242 enqueueOrSpawnTemporaryWaiter strm outputQ out
244 enqueueOrSpawnTemporaryWaiter strm outputQ out
243− dispatchNext strm (CFinish trailers) = do
244− let out = OTrailers strm trailers
245− pri <- readIORef $ streamPriority strm
246− enqueue outputQ out pri
247− dispatchNext _ _ = return ()
248
245
249
246
250 -- Send headers if there is not room for a 1-byte data frame, and return
247 -- Send headers if there is not room for a 1-byte data frame, and return
warp/Network/Wai/Handler/Warp/HTTP2/Types.hs−3
@@ -82,14 +82,11 @@ data Output = OFinish
82 -- MVar whether the promise has been sent.
82 -- MVar whether the promise has been sent.
83 | ONext Stream DynaNext
83 | ONext Stream DynaNext
84 -- ^ Send a chunk of the response.
84 -- ^ Send a chunk of the response.
85− | OTrailers Stream Trailers
86− -- ^ Send a series of trailers in header and continuation frames.
87
85
88outputStream :: Output -> Stream
86outputStream :: Output -> Stream
89outputStream (OResponse strm _ _ _) = strm
87outputStream (OResponse strm _ _ _) = strm
90outputStream (ONext strm _) = strm
88outputStream (ONext strm _) = strm
91outputStream (OPush strm _ _ _ _ _ _) = strm
89outputStream (OPush strm _ _ _ _ _ _) = strm
92−outputStream (OTrailers strm _) = strm
93outputStream _ = error "outputStream"
90outputStream _ = error "outputStream"
94
91
95----------------------------------------------------------------
92----------------------------------------------------------------