@@ -10,6 +10,7 @@ import qualified Data.CaseInsensitive as CI
1010import qualified Network.HTTP.Types as H
1111import Network.Wai.Handler.Warp.Types
1212import Prelude hiding (lines)
13+import Control.Monad
1314
1415-- $setup
1516-- >>> :set -XOverloadedStrings
@@ -36,26 +37,26 @@ parseHeaderLines (firstLine:otherLines) = do
3637--
3738-- >>> parseRequestLine "GET / HTTP/1.1"
3839-- ("GET","/","",HTTP/1.1)
39−-- >>> parseRequestLine "POST /cgi/search.cgi?key=foo HTTP/1.0"
40+-- >>> parseRequestLine "POST /cgi/search.cgi?key=foo HTTP/1.0"
4041-- ("POST","/cgi/search.cgi","?key=foo",HTTP/1.0)
41−-- >>> parseRequestLine "Broken"
42−-- *** Exception: BadFirstLine "Broken"
42+-- >>> parseRequestLine "GET /NoHTTPVersion"
43+-- *** Exception: BadFirstLine "GET /NoHTTPVersion"
44+-- >>> parseRequestLine "GET /NotHTTP UNKNOWN/1.1"
45+-- *** Exception: NonHttp
4346parseRequestLine :: ByteString
4447 -> IO (ByteString, ByteString, ByteString, H.HttpVersion)
45−parseRequestLine s =
46− case filter (not . S.null) $ S.splitWith (\c -> c == 32 || c == 9) s of -- ' '
47− (method:query:http'') -> do
48− let http' = S.concat http''
49− (hfirst, hsecond) = S.splitAt 5 http'
50− if hfirst == "HTTP/"
51− then let (rpath, qstring) = S.breakByte 63 query -- '?'
52− hv =
53− case hsecond of
54− "1.1" -> H.http11
55− _ -> H.http10
56− in return (method, rpath, qstring, hv)
57− else throwIO NonHttp
58− _ -> throwIO $ BadFirstLine $ B.unpack s
48+parseRequestLine requestLine = do
49+ let (method,rest) = S.breakByte 32 requestLine -- ' '
50+ (pathQuery,httpVer') = S.breakByte 32 (S.drop 1 rest) -- ' '
51+ httpVer = S.drop 1 httpVer'
52+ when (rest == "" || httpVer == "") $
53+ throwIO $ BadFirstLine $ B.unpack requestLine
54+ let (path,query) = S.breakByte 63 pathQuery -- '?'
55+ (http,ver) = S.breakByte 47 httpVer -- '/'
56+ when (http /= "HTTP") $ throwIO NonHttp
57+ let hv | ver == "/1.1" = H.http11
58+ | otherwise = H.http10
59+ return $ (method,path,query,hv)
5960
6061----------------------------------------------------------------
6162