@@ -15,6 +15,7 @@ import Data.Conduit
15import qualified Data.IORef as I
15import qualified Data.IORef as I
16import Data.Maybe (fromMaybe)
16import Data.Maybe (fromMaybe)
17import Data.Monoid (mempty)
17import Data.Monoid (mempty)
18+import Data.Void (Void)
18import Data.Word (Word8)
19import Data.Word (Word8)
19import qualified Network.HTTP.Types as H
20import qualified Network.HTTP.Types as H
20import Network.Socket (SockAddr)
21import Network.Socket (SockAddr)
@@ -142,68 +143,69 @@ data THStatus = THStatus
142takeHeaders :: Sink ByteString (ResourceT IO) [ByteString]
143takeHeaders :: Sink ByteString (ResourceT IO) [ByteString]
143takeHeaders =
144takeHeaders =
144 await >>= maybe (throwIO ConnectionClosedByPeer) (push (THStatus 0 id id))
145 await >>= maybe (throwIO ConnectionClosedByPeer) (push (THStatus 0 id id))
146− close :: Sink ByteString (ResourceT IO) a
147− close = throwIO IncompleteHeaders
147+close :: Sink ByteString (ResourceT IO) a
148+close = throwIO IncompleteHeaders
150+push :: THStatus -> ByteString -> Pipe ByteString ByteString Void () (ResourceT IO) [ByteString]
149− push (THStatus len lines prepend) bs
151+push (THStatus len lines prepend) bs
150 -- Too many bytes
152 -- Too many bytes
151 | len > maxTotalHeaderLength = throwIO OverLargeHeader
153 | len > maxTotalHeaderLength = throwIO OverLargeHeader
152− | otherwise =
154+ | otherwise = push' mnl
153− case mnl of
157+ mnl = do
158+ nl <- S.elemIndex 10 bs
159+ -- check if there are two more bytes in the bs
160+ -- if so, see if the second of those is a horizontal space
161+ if bsLen > nl + 1 then
162+ let c = S.index bs (nl + 1)
163+ in Just (nl, c == 32 || c == 9)
167+ {-# INLINE push' #-}
154− -- No newline find in this chunk. Add it to the prepend,
168+ -- No newline find in this chunk. Add it to the prepend,
155− -- update the length, and continue processing.
169+ -- update the length, and continue processing.
156− Nothing ->
170+ push' Nothing = await >>= maybe close (push status)
157− let len' = len + bsLen
172+ len' = len + bsLen
158− prepend' = prepend . S.append bs
173+ prepend' = prepend . S.append bs
159− status = THStatus len' lines prepend'
174+ status = THStatus len' lines prepend'
160− in await >>= maybe close (push status)
161− -- Found a newline, but next line continues as a multiline header
175+ -- Found a newline, but next line continues as a multiline header
162− Just (end, True) ->
176+ push' (Just (end, True)) = push status rest
163− let rest = S.drop (end + 1) bs
178+ rest = S.drop (end + 1) bs
164− prepend' = prepend . S.append (SU.unsafeTake (checkCR bs end) bs)
179+ prepend' = prepend . S.append (SU.unsafeTake (checkCR bs end) bs)
165− len' = len + end
180+ len' = len + end
166− status = THStatus len' lines prepend'
181+ status = THStatus len' lines prepend'
168− -- Found a newline at position end.
182+ -- Found a newline at position end.
169− Just (end, False) ->
183+ push' (Just (end, False))
170− let start = end + 1 -- start of next chunk
184+ -- leftover
172− -- There were some bytes before the newline, get them
173− | end > 0 = prepend $ SU.unsafeTake (checkCR bs end) bs
174− -- No bytes before the newline
175− | otherwise = prepend S.empty
179− let lines' = lines []
185+ | S.null line = let lines' = lines []
181− rest = if start < bsLen
186+ rest = if start < bsLen then
182− then Just (SU.unsafeDrop start bs)
187+ Just (SU.unsafeDrop start bs)
183− else Nothing
189+ Nothing
184− in maybe (return ()) leftover rest >> return lines'
190+ in maybe (return ()) leftover rest >> return lines'
185− -- more headers
191+ -- more headers
187− let len' = len + start
192+ | otherwise = let len' = len + start
188− lines' = lines . (line:)
193+ lines' = lines . (line:)
189− status = THStatus len' lines' id
194+ status = THStatus len' lines' id
190− in if start < bsLen
195+ in if start < bsLen then
191− -- more bytes in this chunk, push again
196+ -- more bytes in this chunk, push again
192− then let bs' = SU.unsafeDrop start bs
197+ let bs' = SU.unsafeDrop start bs
193− in push status bs'
198+ in push status bs'
194− -- no more bytes in this chunk, ask for more
200+ -- no more bytes in this chunk, ask for more
195− else await >>= maybe close (push status)
201+ await >>= maybe close (push status)
197− bsLen = S.length bs
203+ start = end + 1 -- start of next chunk
199− nl <- S.elemIndex 10 bs
205+ -- There were some bytes before the newline, get them
200− -- check if there are two more bytes in the bs
206+ | end > 0 = prepend $ SU.unsafeTake (checkCR bs end) bs
201− -- if so, see if the second of those is a horizontal space
207+ -- No bytes before the newline
202− if bsLen > nl + 1 then
208+ | otherwise = prepend S.empty
203− let c = S.index bs (nl + 1)
204− in Just (nl, c == 32 || c == 9)
208{-# INLINE checkCR #-}
210{-# INLINE checkCR #-}
209checkCR :: ByteString -> Int -> Int
211checkCR :: ByteString -> Int -> Int