packages feed

http-api-data 0.5 → 0.5.1

raw patch · 4 files changed

+89/−28 lines, 4 filesdep ~basedep ~base-compatdep ~text-show

Dependency ranges changed: base, base-compat, text-show

Files

CHANGELOG.md view
@@ -1,3 +1,10 @@+0.5.1+-----++* Add `toEncodedQueryParam` to `ToHttpApiData` type class. It has default+  implementation using `toQueryParam`, but may be overriden with more efficient+  one.+ 0.5 --- 
http-api-data.cabal view
@@ -1,6 +1,6 @@ cabal-version:   >= 1.10 name:            http-api-data-version:         0.5+version:         0.5.1  synopsis:        Converting to/from HTTP API data like URL pieces, headers and query parameters. category:        Web@@ -31,8 +31,9 @@   GHC==8.8.4,   GHC==8.10.7,   GHC==9.0.2,-  GHC==9.2.3,-  GHC==9.4.1+  GHC==9.2.7,+  GHC==9.4.4,+  GHC==9.6.1  flag use-text-show   description: Use text-show library for efficient ToHttpApiData implementations.@@ -44,7 +45,7 @@     include-dirs:   include/      -- GHC bundled-    build-depends:   base                  >= 4.9      && < 4.17+    build-depends:   base                  >= 4.9      && < 4.19                    , bytestring            >= 0.10.8.1 && < 0.12                    , containers            >= 0.5.7.1  && < 0.7                    , text                  >= 1.2.3.0  && < 1.3 || >=2.0 && <2.1@@ -54,7 +55,7 @@     build-depends:                      attoparsec            >= 0.13.2.2 && < 0.15                    , attoparsec-iso8601    >= 1.1.0.0  && < 1.2-                   , base-compat           >= 0.10.5   && < 0.13+                   , base-compat           >= 0.10.5   && < 0.14                    , cookie                >= 0.4.3    && < 0.5                    , hashable              >= 1.2.7.0  && < 1.5                    , http-types            >= 0.12.3   && < 0.13@@ -65,7 +66,7 @@      if flag(use-text-show)       cpp-options: -DUSE_TEXT_SHOW-      build-depends: text-show        >= 3.8.2 && <3.10+      build-depends: text-show        >= 3.8.2 && <3.11      exposed-modules:       Web.HttpApiData
src/Web/Internal/HttpApiData.hs view
@@ -93,10 +93,10 @@   toUrlPiece = toQueryParam    -- | Convert to a URL path piece, making sure to encode any special chars.-  -- The default definition uses 'H.encodePathSegmentsRelative',+  -- The default definition uses @'H.urlEncodeBuilder' 'False'@   -- but this may be overriden with a more efficient version.   toEncodedUrlPiece :: a -> BS.Builder-  toEncodedUrlPiece = H.encodePathSegmentsRelative . (:[]) . toUrlPiece+  toEncodedUrlPiece = H.urlEncodeBuilder False . encodeUtf8 . toUrlPiece    -- | Convert to HTTP header value.   toHeader :: a -> ByteString@@ -106,6 +106,14 @@   toQueryParam :: a -> Text   toQueryParam = toUrlPiece +  -- | Convert to URL query param,+  -- The default definition uses @'H.urlEncodeBuilder' 'True'@+  -- but this may be overriden with a more efficient version.+  --+  -- @since 0.5.1+  toEncodedQueryParam :: a -> BS.Builder+  toEncodedQueryParam = H.urlEncodeBuilder True . encodeUtf8 . toQueryParam+ -- | Parse value from HTTP API data. -- -- __WARNING__: Do not derive this using @DeriveAnyClass@ as the generated@@ -422,12 +430,21 @@ unsafeToEncodedUrlPiece :: ToHttpApiData a => a -> BS.Builder unsafeToEncodedUrlPiece = BS.byteString . encodeUtf8 . toUrlPiece +-- | Convert to a URL-encoded query param using 'toQueryParam'.+-- /Note/: this function does not check if the result contains unescaped characters!+--+-- @since 0.5.1+unsafeToEncodedQueryParam :: ToHttpApiData a => a -> BS.Builder+unsafeToEncodedQueryParam = BS.byteString . encodeUtf8 . toQueryParam+ -- | -- >>> toUrlPiece () -- "_" instance ToHttpApiData () where-  toUrlPiece () = "_"-  toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toUrlPiece _          = "_"+  toHeader _            = "_"+  toEncodedUrlPiece _   = "_"+  toEncodedQueryParam _ = "_"  instance ToHttpApiData Char where   toUrlPiece = T.singleton@@ -438,29 +455,30 @@ instance ToHttpApiData Version where   toUrlPiece = T.pack . showVersion   toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toEncodedQueryParam = unsafeToEncodedQueryParam  instance ToHttpApiData Void    where toUrlPiece = absurd-instance ToHttpApiData Natural where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece+instance ToHttpApiData Natural where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam -instance ToHttpApiData Bool     where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Ordering where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece+instance ToHttpApiData Bool     where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Ordering where toUrlPiece = showTextData; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam -instance ToHttpApiData Double   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Float    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Int      where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Int8     where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Int16    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Int32    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Int64    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Integer  where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Word     where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Word8    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Word16   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Word32   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece-instance ToHttpApiData Word64   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece+instance ToHttpApiData Double   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Float    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Int      where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Int8     where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Int16    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Int32    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Int64    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Integer  where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Word     where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Word8    where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Word16   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Word32   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam+instance ToHttpApiData Word64   where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam  -- | Note: this instance is not polykinded-instance F.HasResolution a => ToHttpApiData (F.Fixed (a :: Type)) where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece+instance F.HasResolution a => ToHttpApiData (F.Fixed (a :: Type)) where toUrlPiece = showt; toEncodedUrlPiece = unsafeToEncodedUrlPiece; toEncodedQueryParam = unsafeToEncodedQueryParam  -- | -- >>> toUrlPiece (fromGregorian 2015 10 03)@@ -468,6 +486,7 @@ instance ToHttpApiData Day where   toUrlPiece = T.pack . show   toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toEncodedQueryParam = unsafeToEncodedQueryParam  timeToUrlPiece :: FormatTime t => String -> t -> Text timeToUrlPiece fmt = T.pack . formatTime defaultTimeLocale (iso8601DateFormat (Just fmt))@@ -478,6 +497,7 @@ instance ToHttpApiData TimeOfDay where   toUrlPiece = T.pack . formatTime defaultTimeLocale "%H:%M:%S%Q"   toEncodedUrlPiece = unsafeToEncodedUrlPiece+  -- no toEncodedQueryParam as : is unsafe char.  -- | -- >>> toUrlPiece $ LocalTime (fromGregorian 2015 10 03) (TimeOfDay 14 55 21.687)@@ -485,6 +505,7 @@ instance ToHttpApiData LocalTime where   toUrlPiece = timeToUrlPiece "%H:%M:%S%Q"   toEncodedUrlPiece = unsafeToEncodedUrlPiece+  -- no toEncodedQueryParam as : is unsafe char.  -- | -- >>> toUrlPiece $ ZonedTime (LocalTime (fromGregorian 2015 10 03) (TimeOfDay 14 55 51.001)) utc@@ -492,6 +513,7 @@ instance ToHttpApiData ZonedTime where   toUrlPiece = timeToUrlPiece "%H:%M:%S%Q%z"   toEncodedUrlPiece = unsafeToEncodedUrlPiece+  -- no toEncodedQueryParam as : is unsafe char.  -- | -- >>> toUrlPiece $ UTCTime (fromGregorian 2015 10 03) 864.5@@ -499,6 +521,7 @@ instance ToHttpApiData UTCTime where   toUrlPiece = timeToUrlPiece "%H:%M:%S%QZ"   toEncodedUrlPiece = unsafeToEncodedUrlPiece+  -- no toEncodedQueryParam as : is unsafe char.  -- | -- >>> toUrlPiece Monday@@ -513,8 +536,9 @@   toUrlPiece Sunday    = "sunday"    toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toEncodedQueryParam = unsafeToEncodedQueryParam --- | +-- | -- >>> toUrlPiece Q4 -- "q4" instance ToHttpApiData QuarterOfYear where@@ -523,6 +547,9 @@   toUrlPiece Q3 = "q3"   toUrlPiece Q4 = "q4" +  toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toEncodedQueryParam = unsafeToEncodedQueryParam+ -- | -- >>> import Data.Time.Calendar.Quarter.Compat (Quarter (..)) -- >>> MkQuarter 8040@@ -540,6 +567,9 @@       f Q3 = "q3"       f Q4 = "q4" +  toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toEncodedQueryParam = unsafeToEncodedQueryParam+ -- | -- >>> import Data.Time.Calendar.Month.Compat (Month (..)) -- >>> MkMonth 24482@@ -551,8 +581,13 @@ instance ToHttpApiData Month where   toUrlPiece = T.pack . formatTime defaultTimeLocale "%Y-%m" +  toEncodedUrlPiece = unsafeToEncodedUrlPiece+  toEncodedQueryParam = unsafeToEncodedQueryParam+ instance ToHttpApiData NominalDiffTime where   toUrlPiece = toUrlPiece . nominalDiffTimeToSeconds++  toEncodedQueryParam = unsafeToEncodedQueryParam   toEncodedUrlPiece = unsafeToEncodedUrlPiece  instance ToHttpApiData String   where toUrlPiece = T.pack@@ -562,46 +597,57 @@ instance ToHttpApiData All where   toUrlPiece        = coerce (toUrlPiece :: Bool -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: Bool -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: Bool -> BS.Builder)  instance ToHttpApiData Any where   toUrlPiece        = coerce (toUrlPiece :: Bool -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: Bool -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: Bool -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Dual a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Sum a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Product a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (First a) where   toUrlPiece        = coerce (toUrlPiece :: Maybe a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: Maybe a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: Maybe a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Last a) where   toUrlPiece        = coerce (toUrlPiece :: Maybe a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: Maybe a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: Maybe a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Semi.Min a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Semi.Max a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Semi.First a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  instance ToHttpApiData a => ToHttpApiData (Semi.Last a) where   toUrlPiece        = coerce (toUrlPiece :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece :: a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  -- | -- >>> toUrlPiece (Just "Hello")@@ -639,6 +685,7 @@   toHeader          = coerce (toHeader :: a -> ByteString)   toQueryParam      = coerce (toQueryParam :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece ::  a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  -- | @since 0.4.2 instance ToHttpApiData a => ToHttpApiData (Const a b) where@@ -646,6 +693,7 @@   toHeader          = coerce (toHeader :: a -> ByteString)   toQueryParam      = coerce (toQueryParam :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece ::  a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  -- | @since 0.4.2 instance ToHttpApiData a => ToHttpApiData (Identity a) where@@ -653,6 +701,7 @@   toHeader          = coerce (toHeader :: a -> ByteString)   toQueryParam      = coerce (toQueryParam :: a -> Text)   toEncodedUrlPiece = coerce (toEncodedUrlPiece ::  a -> BS.Builder)+  toEncodedQueryParam = coerce (toEncodedQueryParam :: a -> BS.Builder)  -- | -- >>> parseUrlPiece "_" :: Either Text ()
test/Web/Internal/HttpApiDataSpec.hs view
@@ -46,6 +46,9 @@ encodedUrlPieceProp :: ToHttpApiData a => a -> Property encodedUrlPieceProp x = toLazyByteString (toEncodedUrlPiece (toUrlPiece x)) === toLazyByteString (toEncodedUrlPiece x) +encodedQueryParamProp :: ToHttpApiData a => a -> Property+encodedQueryParamProp x = toLazyByteString (toEncodedQueryParam (toQueryParam x)) === toLazyByteString (toEncodedQueryParam x)+ -- | Check 'ToHttpApiData' and 'FromHttpApiData' compatibility checkUrlPiece :: forall a. (Eq a, ToHttpApiData a, FromHttpApiData a, Show a, Arbitrary a) => Proxy a -> String -> Spec checkUrlPiece _ = checkUrlPiece' (arbitrary :: Gen a)@@ -56,6 +59,7 @@     prop "toQueryParam <=> parseQueryParam" $ forAll gen (toQueryParam <=> parseQueryParam :: a -> Property)     prop "toHeader <=> parseHeader" $ forAll gen (toHeader <=> parseHeader :: a -> Property)     prop "toEncodedUrlPiece encodes correctly" $ forAll gen encodedUrlPieceProp+    prop "toEncodedQueryParam encodes correctly" $ forAll gen encodedQueryParamProp  -- | Check case insensitivity for @parseUrlPiece@. checkUrlPieceI :: forall a. (Eq a, ToHttpApiData a, FromHttpApiData a, Arbitrary a) => Proxy a -> String -> Spec