packages feed

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 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