on master help sign in
parseHttpAccept
commit0a0f047c2d74331f9ea18ec952ff47b2ec8c3aa1 authorMichael Snoyman <michael@snoyman.com> dateThu 20 May 2010, 00:38 (16 years ago) parenteda31a9
2 files changed+33
Network/Wai/Parse.hs+25 runtests.hs+8
Network/Wai/Parse.hs+25
@@ -3,12 +3,16 @@
33module Network.Wai.Parse
44 ( parseQueryString
55 , parseCookies
6+ , parseHttpAccept
67 ) where
78
89import qualified Data.ByteString as S
10+import qualified Data.ByteString.Char8 as S8
911import Data.Word (Word8)
1012import Data.Bits
1113import Data.Maybe (fromMaybe)
14+import Data.List (sortBy)
15+import Data.Function (on)
1216
1317uncons :: S.ByteString -> Maybe (Word8, S.ByteString)
1418uncons s
@@ -74,3 +78,24 @@ parseCookie s =
7478 let (key, value) = breakDiscard 61 s -- equals sign
7579 key' = S.dropWhile (== 32) key -- space
7680 in (key', value)
81+
82+-- | Parse the HTTP accept string to determine supported content types.
83+parseHttpAccept :: S.ByteString -> [S.ByteString]
84+parseHttpAccept = map fst
85+ . sortBy (rcompare `on` snd)
86+ . map grabQ
87+ . split
88+ where
89+ rcompare x y = compare y x
90+ grabQ s =
91+ let (s', q) = breakDiscard 59 s -- semicolon
92+ (_, q') = breakDiscard 61 q -- equals sign
93+ in (trimWhite s', readQ $ trimWhite q')
94+ readQ s = case reads $ S8.unpack s of
95+ (x, _):_ -> x
96+ _ -> 1.0
97+ trimWhite = S.dropWhile (== 32) -- space
98+ split s
99+ | S.null s = []
100+ | otherwise = let (x, y) = breakDiscard 44 s -- comma
101+ in x : split y
runtests.hs+8
@@ -13,6 +13,7 @@ testSuite :: Test
1313testSuite = testGroup "Network.Wai.Parse"
1414 [ testCase "parseQueryString" caseParseQueryString
1515 , testCase "parseCookies" caseParseCookies
16+ , testCase "parseHttpAccept" caseParseHttpAccept
1617 ]
1718
1819caseParseQueryString :: Assertion
@@ -36,3 +37,10 @@ caseParseCookies = do
3637 let input = B8.pack "a=a1;b=b2; c=c3"
3738 expected = [("a", "a1"), ("b", "b2"), ("c", "c3")]
3839 map (B8.pack *** B8.pack) expected @=? parseCookies input
40+
41+caseParseHttpAccept :: Assertion
42+caseParseHttpAccept = do
43+ let input =
44+ B8.pack "text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"
45+ expected = ["text/html", "text/x-c", "text/x-dvi", "text/plain"]
46+ map B8.pack expected @=? parseHttpAccept input