packages feed

http-api-data 0.6.3 → 0.7

raw patch · 6 files changed

+26/−32 lines, 6 filesdep −unordered-containersdep ~basedep ~containers

Dependencies removed: unordered-containers

Dependency ranges changed: base, containers

Files

CHANGELOG.md view
@@ -1,3 +1,8 @@+0.7++* Change Form representation to use Map (from `containers`) instead of `HashMap`.+  This prevents possible HashDOS attacks.+ 0.6.3  * Add To/FromForm instances for () and Void
http-api-data.cabal view
@@ -1,6 +1,6 @@ cabal-version:   1.12 name:            http-api-data-version:         0.6.3+version:         0.7  synopsis:        Converting to/from HTTP API data like URL pieces, headers and query parameters. category:        Web@@ -56,7 +56,6 @@                    , text-iso8601          >= 0.1.1    && < 0.2                    , tagged                >= 0.8.8    && < 0.9                    , time-compat           >= 1.9.5    && < 1.10-                   , unordered-containers  >= 0.2.20   && < 0.3                    , uuid-types            >= 1.0.6    && < 1.1      if flag(use-text-show)@@ -90,7 +89,7 @@                    , http-api-data                    , text                    , time-compat-                   , unordered-containers+                   , containers                    , uuid-types      build-depends:   hspec                >= 2.7.1    && <2.12
src/Web/Internal/FormUrlEncoded.hs view
@@ -25,14 +25,11 @@ import qualified Data.Foldable              as F import           Data.Functor.Identity      (Identity(Identity)) import           Data.Hashable              (Hashable)-import           Data.HashMap.Strict        (HashMap)-import qualified Data.HashMap.Strict        as HashMap+import qualified Data.Map.Strict            as Map import           Data.Int                   (Int16, Int32, Int64, Int8) import           Data.IntMap                (IntMap) import qualified Data.IntMap                as IntMap import           Data.List                  (intersperse, sortBy)-import           Data.Map                   (Map)-import qualified Data.Map                   as Map import           Data.Monoid                (All (..), Any (..), Dual (..),                                              Product (..), Sum (..)) import           Data.Ord                   (comparing)@@ -205,7 +202,7 @@ -- | The contents of a form, not yet URL-encoded. -- -- 'Form' can be URL-encoded with 'urlEncodeForm' and URL-decoded with 'urlDecodeForm'.-newtype Form = Form { unForm :: HashMap Text [Text] }+newtype Form = Form { unForm :: Map.Map Text [Text] }   deriving (Eq, Read, Generic, Semigroup, Monoid)  instance Show Form where@@ -216,8 +213,8 @@ -- For a stable conversion use 'toListStable'. instance IsList Form where   type Item Form = (Text, Text)-  fromList = Form . HashMap.fromListWith (flip (<>)) . fmap (\(k, v) -> (k, [v]))-  toList = concatMap (\(k, vs) -> map ((,) k) vs) . HashMap.toList . unForm+  fromList = Form . Map.fromListWith (flip (<>)) . fmap (\(k, v) -> (k, [v]))+  toList = concatMap (\(k, vs) -> map ((,) k) vs) . Map.toList . unForm  -- | A stable version of 'toList'. toListStable :: Form -> [(Text, Text)]@@ -275,17 +272,14 @@ -- | -- -- @since 0.6.3-instance ToForm () where toForm _ = Form HashMap.empty+instance ToForm () where toForm _ = Form Map.empty  instance (ToFormKey k, ToHttpApiData v) => ToForm [(k, v)] where   toForm = fromList . map (toFormKey *** toQueryParam) -instance (ToFormKey k, ToHttpApiData v) => ToForm (Map k [v]) where+instance (ToFormKey k, ToHttpApiData v) => ToForm (Map.Map k [v]) where   toForm = fromEntriesByKey . Map.toList -instance (ToFormKey k, ToHttpApiData v) => ToForm (HashMap k [v]) where-  toForm = fromEntriesByKey . HashMap.toList- instance ToHttpApiData v => ToForm (IntMap [v]) where   toForm = fromEntriesByKey . IntMap.toList @@ -294,7 +288,7 @@ -- >>> fromEntriesByKey [("name",["Nick"]),("color",["red","blue"])] -- fromList [("color","red"),("color","blue"),("name","Nick")] fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form-fromEntriesByKey = Form . HashMap.fromListWith (<>) . map (toFormKey *** map toQueryParam)+fromEntriesByKey = Form . Map.fromListWith (<>) . map (toFormKey *** map toQueryParam)  data Proxy3 a b c = Proxy3 @@ -437,12 +431,9 @@ instance (FromFormKey k, FromHttpApiData v) => FromForm [(k, v)] where   fromForm = fmap (concatMap (\(k, vs) -> map ((,) k) vs)) . toEntriesByKey -instance (Ord k, FromFormKey k, FromHttpApiData v) => FromForm (Map k [v]) where+instance (Ord k, Eq k, Hashable k, FromFormKey k, FromHttpApiData v) => FromForm (Map.Map k [v]) where   fromForm = fmap (Map.fromListWith (<>)) . toEntriesByKey -instance (Eq k, Hashable k, FromFormKey k, FromHttpApiData v) => FromForm (HashMap k [v]) where-  fromForm = fmap (HashMap.fromListWith (<>)) . toEntriesByKey- instance FromHttpApiData v => FromForm (IntMap [v]) where   fromForm = fmap (IntMap.fromListWith (<>)) . toEntriesByKey @@ -451,7 +442,7 @@ -- _NOTE:_ this conversion is unstable and may result in different key order -- (but not values). For a stable encoding see 'toEntriesByKeyStable'. toEntriesByKey :: (FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]-toEntriesByKey = traverse parseGroup . HashMap.toList . unForm+toEntriesByKey = traverse parseGroup . Map.toList . unForm   where     parseGroup (k, vs) = (,) <$> parseFormKey k <*> traverse parseQueryParam vs @@ -678,7 +669,7 @@ -- >>> lookupAll "name" [("name", "Oleg"), ("name", "David")] -- ["Oleg","David"] lookupAll :: Text -> Form -> [Text]-lookupAll key = F.concat . HashMap.lookup key . unForm+lookupAll key = F.concat . Map.lookup key . unForm  -- | Lookup an optional value for a key. -- Fail if there is more than one value.
src/Web/Internal/HttpApiData.hs view
@@ -28,11 +28,10 @@ import           Data.Functor.Identity        (Identity(Identity)) import           Data.Int                     (Int16, Int32, Int64, Int8) import           Data.Kind                    (Type)-import qualified Data.Map                     as Map+import qualified Data.Map.Strict              as Map import           Data.Monoid                  (All (..), Any (..), Dual (..),                                                First (..), Last (..),                                                Product (..), Sum (..))-import           Data.Semigroup               (Semigroup (..)) import qualified Data.Semigroup               as Semi import           Data.Tagged                  (Tagged (..)) import           Data.Text                    (Text)
test/Web/Internal/FormUrlEncodedSpec.hs view
@@ -4,7 +4,7 @@  import Control.Monad ((<=<)) import qualified Data.ByteString.Lazy.Char8 as BSL-import qualified Data.HashMap.Strict as HashMap+import qualified Data.Map.Strict            as Map import Data.Text (Text, unpack) import Test.Hspec import Test.QuickCheck@@ -27,13 +27,13 @@      it "contains the record names" $ property $ \(x :: SimpleRec) -> do       let f = unForm $ toForm x-      HashMap.member "rec1" f `shouldBe` True-      HashMap.member "rec2" f `shouldBe` True+      Map.member "rec1" f `shouldBe` True+      Map.member "rec2" f `shouldBe` True      it "contains the correct record values" $ property $ \(x :: SimpleRec) -> do       let f = unForm $ toForm x-      HashMap.lookup "rec1" f `shouldBe` Just [rec1 x]-      (parseQueryParams <$> HashMap.lookup "rec2" f) `shouldBe` Just (Right [rec2 x])+      Map.lookup "rec1" f `shouldBe` Just [rec1 x]+      (parseQueryParams <$> Map.lookup "rec2" f) `shouldBe` Just (Right [rec2 x])    context "FromForm" $ do 
test/Web/Internal/TestInstances.hs view
@@ -8,9 +8,9 @@    , NoEmptyKeyForm(..)    ) where -import           Control.Applicative+import           Control.Applicative  -- for ghc < 9.6 import           Data.Char-import qualified Data.HashMap.Strict  as HashMap+import qualified Data.Map.Strict      as Map import qualified Data.Text            as T import           Data.Time.Compat import           GHC.Exts             (fromList)@@ -63,4 +63,4 @@ instance Arbitrary NoEmptyKeyForm where   arbitrary = NoEmptyKeyForm . removeEmptyKeys <$> arbitrary     where-      removeEmptyKeys (Form m) = Form (HashMap.delete "" m)+      removeEmptyKeys (Form m) = Form (Map.delete "" m)