on master help sign in
warp: add HTTP2 CONNECT support

As per section 8.3 of HTTP2 spec, ":scheme" and ":path" should be omitted and ":authority" is mandatory for HTTP2 CONNECT request. Treat CONNECT request as a special case for headers check. And also for CONNECT request, use ":authority" as unparsed path, so that CONNECT method has consistent behavior compare to HTTP 1.0. Closes #561

commit2b596d992a93f383e6eaa2ddc7f52d8e52f0a0e8 authorBin Jin <bjin@ctrl-d.org> dateTue 26 Jul 2016, 11:08 (10 years ago) parentfdb77ec
2 files changed+19−9
warp/Network/Wai/Handler/Warp/HTTP2/HPACK.hs+15−7 warp/Network/Wai/Handler/Warp/HTTP2/Request.hs+4−2
warp/Network/Wai/Handler/Warp/HTTP2/HPACK.hs+15−7
@@ -83,13 +83,21 @@ hpackDecodeHeader hdrblk Context{..} = do
8383{-# INLINE checkRequestHeader #-}
8484checkRequestHeader :: ValueTable -> Bool
8585checkRequestHeader reqvt
86− | getHeaderValue tokenStatus reqvt /= Nothing = False
87− | getHeaderValue tokenPath reqvt == Nothing = False
88− | getHeaderValue tokenMethod reqvt == Nothing = False
89− | getHeaderValue tokenAuthority reqvt == Nothing = False
90− | getHeaderValue tokenConnection reqvt /= Nothing = False
91− | just (getHeaderValue tokenTE reqvt) (/= "trailers") = False
92− | otherwise = True
86+ | mStatus /= Nothing = False
87+ | mMethod == Nothing = False
88+ | mAuthority == Nothing = False
89+ | mConnection /= Nothing = False
90+ | just mTE (/= "trailers") = False
91+ | just mMethod (== "CONNECT") = mPath == Nothing && mScheme == Nothing
92+ | otherwise = mPath /= Nothing
93+ where
94+ mStatus = getHeaderValue tokenStatus reqvt
95+ mScheme = getHeaderValue tokenScheme reqvt
96+ mPath = getHeaderValue tokenPath reqvt
97+ mMethod = getHeaderValue tokenMethod reqvt
98+ mAuthority = getHeaderValue tokenAuthority reqvt
99+ mConnection = getHeaderValue tokenConnection reqvt
100+ mTE = getHeaderValue tokenTE reqvt
93101
94102{-# INLINE just #-}
95103just :: Maybe a -> (a -> Bool) -> Bool
warp/Network/Wai/Handler/Warp/HTTP2/Request.hs+4−2
@@ -67,14 +67,16 @@ mkRequest' ii1 settings addr ref (reqths,reqvt) body = return (req,ii)
6767 Nothing -> case mAuth of
6868 Just auth -> (tokenHost, auth) : reqths
6969 _ -> reqths
70− !colonPath = fromJust $ getHeaderValue tokenPath reqvt -- MUST
70+ !mPath = getHeaderValue tokenPath reqvt -- SHOULD
7171 !colonMethod = fromJust $ getHeaderValue tokenMethod reqvt -- MUST
7272 !mAuth = getHeaderValue tokenAuthority reqvt -- SHOULD
7373 !mHost = getHeaderValue tokenHost reqvt
7474 !mRange = getHeaderValue tokenRange reqvt
7575 !mReferer = getHeaderValue tokenReferer reqvt
7676 !mUserAgent = getHeaderValue tokenUserAgent reqvt
77− (unparsedPath,query) = B8.break (=='?') colonPath
77+ -- CONNECT request will have ":path" omitted, use ":authority" as unparsed
78+ -- path instead so that it will have consistent behavior compare to HTTP 1.0
79+ (unparsedPath,query) = B8.break (=='?') $ fromJust (mPath <|> mAuth)
7880 !path = H.extractPath unparsedPath
7981 !rawPath = if S.settingsNoParsePath settings then unparsedPath else path
8082 !h = hashByteString rawPath