wai-extra 1.3.1.1 → 1.3.2
raw patch · 3 files changed
+54/−18 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Network.Wai.Parse: parseContentType :: ByteString -> (ByteString, [(ByteString, ByteString)])
Files
- Network/Wai/Parse.hs +31/−17
- test/WaiExtraTest.hs +22/−0
- wai-extra.cabal +1/−1
Network/Wai/Parse.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE PatternGuards #-} -- | Some helpers for parsing data out of a raw WAI 'Request'. module Network.Wai.Parse@@ -17,6 +18,7 @@ , Param , File , FileInfo (..)+ , parseContentType #if TEST , Bound (..) , findBound@@ -126,24 +128,36 @@ getRequestBodyType :: Request -> Maybe RequestBodyType getRequestBodyType req = do- ctype <- lookup "Content-Type" $ requestHeaders req- if urlenc `S.isPrefixOf` ctype- then Just UrlEncoded- else case boundary ctype of- Just x -> Just $ Multipart x- Nothing -> Nothing+ ctype' <- lookup "Content-Type" $ requestHeaders req+ let (ctype, attrs) = parseContentType ctype'+ case ctype of+ "application/x-www-form-urlencoded" -> return UrlEncoded+ "multipart/form-data" | Just bound <- lookup "boundary" attrs -> return $ Multipart bound+ _ -> Nothing++-- | Parse a content type value, turning a single @ByteString@ into the actual+-- content type and a list of pairs of attributes.+--+-- Since 1.3.2+parseContentType :: S.ByteString -> (S.ByteString, [(S.ByteString, S.ByteString)])+parseContentType a = do+ let (ctype, b) = S.break (== semicolon) a+ attrs = goAttrs id $ S.drop 1 b+ in (ctype, attrs) where- urlenc = S8.pack "application/x-www-form-urlencoded"- formBound = S8.pack "multipart/form-data;"- bound' = "boundary="- boundary s =- if "multipart/form-data;" `S.isPrefixOf` s- then- let s' = S.dropWhile (== 32) $ S.drop (S.length formBound) s- in if bound' `S.isPrefixOf` s'- then Just $ S.drop (S.length bound') s'- else Nothing- else Nothing+ semicolon = 59+ equals = 61+ space = 32+ goAttrs front bs+ | S.null bs = front []+ | otherwise =+ let (x, rest) = S.break (== semicolon) bs+ in goAttrs (front . (goAttr x:)) $ S.drop 1 rest+ goAttr bs =+ let (k, v') = S.break (== equals) bs+ v = S.drop 1 v'+ in (strip k, strip v)+ strip = S.dropWhile (== space) . fst . S.breakEnd (/= space) parseRequestBody :: BackEnd y -> Request
test/WaiExtraTest.hs view
@@ -12,6 +12,7 @@ import qualified Data.ByteString.Lazy.Char8 as L8 import qualified Data.ByteString.Lazy as L import qualified Data.Text.Lazy as T+import qualified Data.Text as TS import qualified Data.Text.Encoding as TE import Control.Arrow @@ -38,11 +39,19 @@ specs :: Spec specs = do describe "Network.Wai.Parse" $ do+ describe "parseContentType" $ do+ let go (x, y, z) = it (TS.unpack $ TE.decodeUtf8 x) $ parseContentType x `shouldBe` (y, z)+ mapM_ go+ [ ("text/plain", "text/plain", [])+ , ("text/plain; charset=UTF-8 ", "text/plain", [("charset", "UTF-8")])+ , ("text/plain; charset=UTF-8 ; boundary = foo", "text/plain", [("charset", "UTF-8"), ("boundary", "foo")])+ ] it "parseQueryString" caseParseQueryString it "parseQueryString with question mark" caseParseQueryStringQM it "parseHttpAccept" caseParseHttpAccept it "parseRequestBody" caseParseRequestBody it "multipart with plus" caseMultipartPlus+ it "multipart with multiple attributes" caseMultipartAttrs it "urlencoded with plus" caseUrlEncPlus {- , it "findBound" caseFindBound@@ -187,6 +196,19 @@ "has+plus\n" ++ "--AaB03x--" ctype = "multipart/form-data; boundary=AaB03x"++caseMultipartAttrs :: Assertion+caseMultipartAttrs = do+ result <- C.runResourceT $ parseRequestBody' lbsBackEnd $ toRequest ctype content+ liftIO $ result @?= ([("email", "has+plus")], [])+ where+ content = S8.pack $+ "--AaB03x\n" +++ "Content-Disposition: form-data; name=\"email\"\n" +++ "Content-Type: text/plain; charset=iso-8859-1\n\n" +++ "has+plus\n" +++ "--AaB03x--"+ ctype = "multipart/form-data; charset=UTF-8; boundary=AaB03x" caseUrlEncPlus :: Assertion caseUrlEncPlus = do
wai-extra.cabal view
@@ -1,5 +1,5 @@ Name: wai-extra-Version: 1.3.1.1+Version: 1.3.2 Synopsis: Provides some basic WAI handlers and middleware. Description: The goal here is to provide common features without many dependencies. License: MIT