-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Converting to/from HTTP API data like URL pieces, headers and query parameters. -- -- This package defines typeclasses used for converting Haskell data -- types to and from HTTP API data. -- -- Please see README.md @package http-api-data @version 0.3.8 -- | Convert Haskell values to and from HTTP API data such as URL pieces, -- headers and query parameters. module Web.Internal.HttpApiData -- | Convert value to HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class ToHttpApiData a -- | Convert to URL path piece. toUrlPiece :: ToHttpApiData a => a -> Text -- | Convert to a URL path piece, making sure to encode any special chars. -- The default definition uses encodePathSegmentsRelative, but -- this may be overriden with a more efficient version. toEncodedUrlPiece :: ToHttpApiData a => a -> Builder -- | Convert to HTTP header value. toHeader :: ToHttpApiData a => a -> ByteString -- | Convert to query param value. toQueryParam :: ToHttpApiData a => a -> Text -- | Parse value from HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class FromHttpApiData a -- | Parse URL path piece. parseUrlPiece :: FromHttpApiData a => Text -> Either Text a -- | Parse HTTP header value. parseHeader :: FromHttpApiData a => ByteString -> Either Text a -- | Parse query param value. parseQueryParam :: FromHttpApiData a => Text -> Either Text a -- | Convert multiple values to a list of URL pieces. -- --
--   >>> toUrlPieces [1, 2, 3] :: [Text]
--   ["1","2","3"]
--   
toUrlPieces :: (Functor t, ToHttpApiData a) => t a -> t Text -- | Parse multiple URL pieces. -- --
--   >>> parseUrlPieces ["true", "false"] :: Either Text [Bool]
--   Right [True,False]
--   
--   >>> parseUrlPieces ["123", "hello", "world"] :: Either Text [Int]
--   Left "could not parse: `hello' (input does not start with a digit)"
--   
parseUrlPieces :: (Traversable t, FromHttpApiData a) => t Text -> Either Text (t a) -- | Convert multiple values to a list of query parameter values. -- --
--   >>> toQueryParams [fromGregorian 2015 10 03, fromGregorian 2015 12 01] :: [Text]
--   ["2015-10-03","2015-12-01"]
--   
toQueryParams :: (Functor t, ToHttpApiData a) => t a -> t Text -- | Parse multiple query parameters. -- --
--   >>> parseQueryParams ["1", "2", "3"] :: Either Text [Int]
--   Right [1,2,3]
--   
--   >>> parseQueryParams ["64", "128", "256"] :: Either Text [Word8]
--   Left "out of bounds: `256' (should be between 0 and 255)"
--   
parseQueryParams :: (Traversable t, FromHttpApiData a) => t Text -> Either Text (t a) -- | Parse URL path piece in a Maybe. -- --
--   >>> parseUrlPieceMaybe "12" :: Maybe Int
--   Just 12
--   
parseUrlPieceMaybe :: FromHttpApiData a => Text -> Maybe a -- | Parse HTTP header value in a Maybe. -- --
--   >>> parseHeaderMaybe "hello" :: Maybe Text
--   Just "hello"
--   
parseHeaderMaybe :: FromHttpApiData a => ByteString -> Maybe a -- | Parse query param value in a Maybe. -- --
--   >>> parseQueryParamMaybe "true" :: Maybe Bool
--   Just True
--   
parseQueryParamMaybe :: FromHttpApiData a => Text -> Maybe a -- | Default parsing error. defaultParseError :: Text -> Either Text a -- | Convert Maybe parser into Either -- Text parser with default error message. parseMaybeTextData :: (Text -> Maybe a) -> (Text -> Either Text a) -- | Lower case. -- -- Convert to URL piece using Show instance. The result -- is always lower cased. -- --
--   >>> showTextData True
--   "true"
--   
-- -- This can be used as a default implementation for enumeration types: -- --
--   >>> data MyData = Foo | Bar | Baz deriving (Show)
--   
--   >>> instance ToHttpApiData MyData where toUrlPiece = showTextData
--   
--   >>> toUrlPiece Foo
--   "foo"
--   
showTextData :: Show a => a -> Text -- | Like show, but returns Text. showt :: Show a => a -> Text -- | Case insensitive. -- -- Parse given text case insensitive and then parse the rest of the input -- using parseUrlPiece. -- --
--   >>> parseUrlPieceWithPrefix "Just " "just 10" :: Either Text Int
--   Right 10
--   
--   >>> parseUrlPieceWithPrefix "Left " "left" :: Either Text Bool
--   Left "could not parse: `left'"
--   
-- -- This can be used to implement FromHttpApiData for -- single field constructors: -- --
--   >>> data Foo = Foo Int deriving (Show)
--   
--   >>> instance FromHttpApiData Foo where parseUrlPiece s = Foo <$> parseUrlPieceWithPrefix "Foo " s
--   
--   >>> parseUrlPiece "foo 1" :: Either Text Foo
--   Right (Foo 1)
--   
parseUrlPieceWithPrefix :: FromHttpApiData a => Text -> Text -> Either Text a -- | Parse given bytestring then parse the rest of the input using -- parseHeader. -- --
--   data BasicAuthToken = BasicAuthToken Text deriving (Show)
--   
--   instance FromHttpApiData BasicAuthToken where
--     parseHeader h     = BasicAuthToken <$> parseHeaderWithPrefix "Basic " h
--     parseQueryParam p = BasicAuthToken <$> parseQueryParam p
--   
-- --
--   >>> parseHeader "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" :: Either Text BasicAuthToken
--   Right (BasicAuthToken "QWxhZGRpbjpvcGVuIHNlc2FtZQ==")
--   
parseHeaderWithPrefix :: FromHttpApiData a => ByteString -> ByteString -> Either Text a -- | Case insensitive. -- -- Parse given text case insensitive and then parse the rest of the input -- using parseQueryParam. -- --
--   >>> parseQueryParamWithPrefix "z" "z10" :: Either Text Int
--   Right 10
--   
parseQueryParamWithPrefix :: FromHttpApiData a => Text -> Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on Show -- instance. -- --
--   >>> parseBoundedTextData "true" :: Either Text Bool
--   Right True
--   
--   >>> parseBoundedTextData "FALSE" :: Either Text Bool
--   Right False
--   
-- -- This can be used as a default implementation for enumeration types: -- --
--   >>> data MyData = Foo | Bar | Baz deriving (Show, Bounded, Enum)
--   
--   >>> instance FromHttpApiData MyData where parseUrlPiece = parseBoundedTextData
--   
--   >>> parseUrlPiece "foo" :: Either Text MyData
--   Right Foo
--   
parseBoundedTextData :: (Show a, Bounded a, Enum a) => Text -> Either Text a -- | Lookup values based on a precalculated mapping of their -- representations. lookupBoundedEnumOf :: (Bounded a, Enum a, Eq b) => (a -> b) -> b -> Maybe a -- | Parse values based on a precalculated mapping of their -- Text representation. -- --
--   >>> parseBoundedEnumOf toUrlPiece "true" :: Either Text Bool
--   Right True
--   
-- -- For case sensitive parser see parseBoundedEnumOfI. parseBoundedEnumOf :: (Bounded a, Enum a) => (a -> Text) -> Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on a precalculated mapping of -- their Text representations. -- --
--   >>> parseBoundedEnumOfI toUrlPiece "FALSE" :: Either Text Bool
--   Right False
--   
-- -- For case sensitive parser see parseBoundedEnumOf. parseBoundedEnumOfI :: (Bounded a, Enum a) => (a -> Text) -> Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on ToHttpApiData -- instance. Uses toUrlPiece to get possible values. parseBoundedUrlPiece :: (ToHttpApiData a, Bounded a, Enum a) => Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on ToHttpApiData -- instance. Uses toQueryParam to get possible values. parseBoundedQueryParam :: (ToHttpApiData a, Bounded a, Enum a) => Text -> Either Text a -- | Parse values based on ToHttpApiData instance. Uses -- toHeader to get possible values. parseBoundedHeader :: (ToHttpApiData a, Bounded a, Enum a) => ByteString -> Either Text a -- | Parse URL piece using Read instance. -- -- Use for types which do not involve letters: -- --
--   >>> readTextData "1991-06-02" :: Either Text Day
--   Right 1991-06-02
--   
-- -- This parser is case sensitive and will not match -- showTextData in presence of letters: -- --
--   >>> readTextData (showTextData True) :: Either Text Bool
--   Left "could not parse: `true'"
--   
-- -- See parseBoundedTextData. readTextData :: Read a => Text -> Either Text a -- | Run Reader as HTTP API data parser. runReader :: Reader a -> Text -> Either Text a -- | Run Reader to parse bounded integral value with bounds -- checking. -- --
--   >>> parseBounded decimal "256" :: Either Text Word8
--   Left "out of bounds: `256' (should be between 0 and 255)"
--   
parseBounded :: forall a. (Bounded a, Integral a) => Reader Integer -> Text -> Either Text a -- | Convert to a URL-encoded path piece using toUrlPiece. -- Note: this function does not check if the result contains -- unescaped characters! This function can be used to override -- toEncodedUrlPiece as a more efficient implementation when the -- resulting URL piece never has to be escaped. unsafeToEncodedUrlPiece :: ToHttpApiData a => a -> Builder -- |
--   >>> toUrlPiece ()
--   "_"
--   
-- |
--   >>> toUrlPiece (Version [1, 2, 3] [])
--   "1.2.3"
--   
-- |
--   >>> toUrlPiece (fromGregorian 2015 10 03)
--   "2015-10-03"
--   
timeToUrlPiece :: FormatTime t => String -> t -> Text -- |
--   >>> toUrlPiece $ TimeOfDay 14 55 23.1
--   "14:55:23.1"
--   
-- |
--   >>> toUrlPiece $ LocalTime (fromGregorian 2015 10 03) (TimeOfDay 14 55 21.687)
--   "2015-10-03T14:55:21.687"
--   
-- |
--   >>> toUrlPiece $ ZonedTime (LocalTime (fromGregorian 2015 10 03) (TimeOfDay 14 55 51.001)) utc
--   "2015-10-03T14:55:51.001+0000"
--   
-- |
--   >>> toUrlPiece $ UTCTime (fromGregorian 2015 10 03) 864.5
--   "2015-10-03T00:14:24.5Z"
--   
-- |
--   >>> toUrlPiece (Just "Hello")
--   "just Hello"
--   
-- |
--   >>> toUrlPiece (Left "err" :: Either String Int)
--   "left err"
--   
--   >>> toUrlPiece (Right 3 :: Either String Int)
--   "right 3"
--   
-- |
--   >>> parseUrlPiece "_" :: Either Text ()
--   Right ()
--   
-- |
--   >>> showVersion <$> parseUrlPiece "1.2.3"
--   Right "1.2.3"
--   
-- | Parsing a Void value is always an error, considering -- Void as a data type with no constructors. -- |
--   >>> toGregorian <$> parseUrlPiece "2016-12-01"
--   Right (2016,12,1)
--   
-- |
--   >>> parseUrlPiece "14:55:01.333" :: Either Text TimeOfDay
--   Right 14:55:01.333
--   
-- |
--   >>> parseUrlPiece "2015-10-03T14:55:01" :: Either Text LocalTime
--   Right 2015-10-03 14:55:01
--   
-- |
--   >>> parseUrlPiece "2015-10-03T14:55:01+0000" :: Either Text ZonedTime
--   Right 2015-10-03 14:55:01 +0000
--   
-- --
--   >>> parseQueryParam "2016-12-31T01:00:00Z" :: Either Text ZonedTime
--   Right 2016-12-31 01:00:00 +0000
--   
-- |
--   >>> parseUrlPiece "2015-10-03T00:14:24Z" :: Either Text UTCTime
--   Right 2015-10-03 00:14:24 UTC
--   
-- |
--   >>> parseUrlPiece "Just 123" :: Either Text (Maybe Int)
--   Right (Just 123)
--   
-- |
--   >>> parseUrlPiece "Right 123" :: Either Text (Either String Int)
--   Right (Right 123)
--   
-- | Lenient parameters. FromHttpApiData combinators always return -- Right. newtype LenientData a LenientData :: Either Text a -> LenientData a [getLenientData] :: LenientData a -> Either Text a runAtto :: Parser a -> Text -> Either Text a instance Data.Traversable.Traversable Web.Internal.HttpApiData.LenientData instance Data.Foldable.Foldable Web.Internal.HttpApiData.LenientData instance GHC.Base.Functor Web.Internal.HttpApiData.LenientData instance Data.Data.Data a => Data.Data.Data (Web.Internal.HttpApiData.LenientData a) instance GHC.Read.Read a => GHC.Read.Read (Web.Internal.HttpApiData.LenientData a) instance GHC.Show.Show a => GHC.Show.Show (Web.Internal.HttpApiData.LenientData a) instance GHC.Classes.Ord a => GHC.Classes.Ord (Web.Internal.HttpApiData.LenientData a) instance GHC.Classes.Eq a => GHC.Classes.Eq (Web.Internal.HttpApiData.LenientData a) instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (Web.Internal.HttpApiData.LenientData a) instance Web.Internal.HttpApiData.FromHttpApiData () instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Char instance Web.Internal.HttpApiData.FromHttpApiData Data.Version.Version instance Web.Internal.HttpApiData.FromHttpApiData Data.Void.Void instance Web.Internal.HttpApiData.FromHttpApiData GHC.Natural.Natural instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Bool instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Ordering instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Double instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Float instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Int instance Web.Internal.HttpApiData.FromHttpApiData GHC.Int.Int8 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Int.Int16 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Int.Int32 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Int.Int64 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Integer.Type.Integer instance Web.Internal.HttpApiData.FromHttpApiData GHC.Types.Word instance Web.Internal.HttpApiData.FromHttpApiData GHC.Word.Word8 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Word.Word16 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Word.Word32 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Word.Word64 instance Web.Internal.HttpApiData.FromHttpApiData GHC.Base.String instance Web.Internal.HttpApiData.FromHttpApiData Data.Text.Internal.Text instance Web.Internal.HttpApiData.FromHttpApiData Data.Text.Internal.Lazy.Text instance Web.Internal.HttpApiData.FromHttpApiData Data.Time.Calendar.Days.Day instance Web.Internal.HttpApiData.FromHttpApiData Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay instance Web.Internal.HttpApiData.FromHttpApiData Data.Time.LocalTime.Internal.LocalTime.LocalTime instance Web.Internal.HttpApiData.FromHttpApiData Data.Time.LocalTime.Internal.ZonedTime.ZonedTime instance Web.Internal.HttpApiData.FromHttpApiData Data.Time.Clock.Internal.UTCTime.UTCTime instance Web.Internal.HttpApiData.FromHttpApiData Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime instance Web.Internal.HttpApiData.FromHttpApiData Data.Monoid.All instance Web.Internal.HttpApiData.FromHttpApiData Data.Monoid.Any instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (Data.Monoid.Dual a) instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (Data.Monoid.Sum a) instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (Data.Monoid.Product a) instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (Data.Monoid.First a) instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (Data.Monoid.Last a) instance Web.Internal.HttpApiData.FromHttpApiData a => Web.Internal.HttpApiData.FromHttpApiData (GHC.Base.Maybe a) instance (Web.Internal.HttpApiData.FromHttpApiData a, Web.Internal.HttpApiData.FromHttpApiData b) => Web.Internal.HttpApiData.FromHttpApiData (Data.Either.Either a b) instance Web.Internal.HttpApiData.FromHttpApiData Data.UUID.Types.Internal.UUID instance Web.Internal.HttpApiData.ToHttpApiData () instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Char instance Web.Internal.HttpApiData.ToHttpApiData Data.Version.Version instance Web.Internal.HttpApiData.ToHttpApiData Data.Void.Void instance Web.Internal.HttpApiData.ToHttpApiData GHC.Natural.Natural instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Bool instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Ordering instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Double instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Float instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Int instance Web.Internal.HttpApiData.ToHttpApiData GHC.Int.Int8 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Int.Int16 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Int.Int32 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Int.Int64 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Integer.Type.Integer instance Web.Internal.HttpApiData.ToHttpApiData GHC.Types.Word instance Web.Internal.HttpApiData.ToHttpApiData GHC.Word.Word8 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Word.Word16 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Word.Word32 instance Web.Internal.HttpApiData.ToHttpApiData GHC.Word.Word64 instance Web.Internal.HttpApiData.ToHttpApiData Data.Time.Calendar.Days.Day instance Web.Internal.HttpApiData.ToHttpApiData Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay instance Web.Internal.HttpApiData.ToHttpApiData Data.Time.LocalTime.Internal.LocalTime.LocalTime instance Web.Internal.HttpApiData.ToHttpApiData Data.Time.LocalTime.Internal.ZonedTime.ZonedTime instance Web.Internal.HttpApiData.ToHttpApiData Data.Time.Clock.Internal.UTCTime.UTCTime instance Web.Internal.HttpApiData.ToHttpApiData Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime instance Web.Internal.HttpApiData.ToHttpApiData GHC.Base.String instance Web.Internal.HttpApiData.ToHttpApiData Data.Text.Internal.Text instance Web.Internal.HttpApiData.ToHttpApiData Data.Text.Internal.Lazy.Text instance Web.Internal.HttpApiData.ToHttpApiData Data.Monoid.All instance Web.Internal.HttpApiData.ToHttpApiData Data.Monoid.Any instance Web.Internal.HttpApiData.ToHttpApiData a => Web.Internal.HttpApiData.ToHttpApiData (Data.Monoid.Dual a) instance Web.Internal.HttpApiData.ToHttpApiData a => Web.Internal.HttpApiData.ToHttpApiData (Data.Monoid.Sum a) instance Web.Internal.HttpApiData.ToHttpApiData a => Web.Internal.HttpApiData.ToHttpApiData (Data.Monoid.Product a) instance Web.Internal.HttpApiData.ToHttpApiData a => Web.Internal.HttpApiData.ToHttpApiData (Data.Monoid.First a) instance Web.Internal.HttpApiData.ToHttpApiData a => Web.Internal.HttpApiData.ToHttpApiData (Data.Monoid.Last a) instance Web.Internal.HttpApiData.ToHttpApiData a => Web.Internal.HttpApiData.ToHttpApiData (GHC.Base.Maybe a) instance (Web.Internal.HttpApiData.ToHttpApiData a, Web.Internal.HttpApiData.ToHttpApiData b) => Web.Internal.HttpApiData.ToHttpApiData (Data.Either.Either a b) instance Web.Internal.HttpApiData.ToHttpApiData Data.UUID.Types.Internal.UUID module Web.Internal.FormUrlEncoded -- | Typeclass for types that can be used as keys in a Form-like -- container (like Map). class ToFormKey k -- | Render a key for a Form. toFormKey :: ToFormKey k => k -> Text -- | Typeclass for types that can be parsed from keys of a Form. -- This is the reverse of ToFormKey. class FromFormKey k -- | Parse a key of a Form. parseFormKey :: FromFormKey k => Text -> Either Text k -- | The contents of a form, not yet URL-encoded. -- -- Form can be URL-encoded with urlEncodeForm and -- URL-decoded with urlDecodeForm. newtype Form Form :: HashMap Text [Text] -> Form [unForm] :: Form -> HashMap Text [Text] -- | _NOTE:_ toList is unstable and may result in different key -- order (but not values). For a stable conversion use -- toListStable. -- | A stable version of toList. toListStable :: Form -> [(Text, Text)] -- | Convert a value into Form. -- -- An example type and instance: -- --
--   {-# LANGUAGE OverloadedLists #-}
--   
--   data Person = Person
--     { name :: String
--     , age  :: Int }
--   
--   instance ToForm Person where
--     toForm person =
--       [ ("name", toQueryParam (name person))
--       , ("age", toQueryParam (age person)) ]
--   
-- -- Instead of manually writing ToForm instances you can -- use a default generic implementation of toForm. -- -- To do that, simply add deriving Generic clause to your -- datatype and declare a ToForm instance for your datatype -- without giving definition for toForm. -- -- For instance, the previous example can be simplified into this: -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
--   instance ToForm Person
--   
-- -- The default implementation of toForm is genericToForm. class ToForm a -- | Convert a value into Form. toForm :: ToForm a => a -> Form -- | Convert a value into Form. toForm :: (ToForm a, Generic a, GToForm a (Rep a)) => a -> Form -- | Convert a list of entries groupped by key into a Form. -- --
--   >>> fromEntriesByKey [("name",["Nick"]),("color",["red","blue"])]
--   fromList [("color","red"),("color","blue"),("name","Nick")]
--   
fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form data Proxy3 a b c Proxy3 :: Proxy3 a b c -- | A Generic-based implementation of toForm. This is used -- as a default implementation in ToForm. -- -- Note that this only works for records (i.e. product data types with -- named fields): -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
-- -- In this implementation each field's value gets encoded using -- toQueryParam. Two field types are exceptions: -- -- -- -- Here's an example: -- --
--   data Post = Post
--     { title    :: String
--     , subtitle :: Maybe String
--     , comments :: [String]
--     } deriving (Generic, Show)
--   
--   instance ToForm Post
--   
-- --
--   >>> urlEncodeAsFormStable Post { title = "Test", subtitle = Nothing, comments = ["Nice post!", "+1"] }
--   "comments=Nice%20post%21&comments=%2B1&title=Test"
--   
genericToForm :: forall a. (Generic a, GToForm a (Rep a)) => FormOptions -> a -> Form class GToForm t (f :: * -> *) gToForm :: GToForm t f => Proxy t -> FormOptions -> f x -> Form -- | Parse Form into a value. -- -- An example type and instance: -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int }
--   
--   instance FromForm Person where
--     fromForm f = Person
--       <$> parseUnique "name" f
--       <*> parseUnique "age"  f
--   
-- -- Instead of manually writing FromForm instances you can -- use a default generic implementation of fromForm. -- -- To do that, simply add deriving Generic clause to your -- datatype and declare a FromForm instance for your datatype -- without giving definition for fromForm. -- -- For instance, the previous example can be simplified into this: -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
--   instance FromForm Person
--   
-- -- The default implementation of fromForm is -- genericFromForm. It only works for records and it will use -- parseQueryParam for each field's value. class FromForm a -- | Parse Form into a value. fromForm :: FromForm a => Form -> Either Text a -- | Parse Form into a value. fromForm :: (FromForm a, Generic a, GFromForm a (Rep a)) => Form -> Either Text a -- | _NOTE:_ this conversion is unstable and may result in different key -- order (but not values). -- | Parse a Form into a list of entries groupped by key. -- -- _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])] -- | Parse a Form into a list of entries groupped by key. -- --
--   >>> toEntriesByKeyStable [("name", "Nick"), ("color", "red"), ("color", "white")] :: Either Text [(Text, [Text])]
--   Right [("color",["red","white"]),("name",["Nick"])]
--   
-- -- For an unstable (but faster) conversion see toEntriesByKey. toEntriesByKeyStable :: (Ord k, FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])] -- | A Generic-based implementation of fromForm. This is used -- as a default implementation in FromForm. -- -- Note that this only works for records (i.e. product data types with -- named fields): -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
-- -- In this implementation each field's value gets decoded using -- parseQueryParam. Two field types are exceptions: -- -- -- -- Here's an example: -- --
--   data Post = Post
--     { title    :: String
--     , subtitle :: Maybe String
--     , comments :: [String]
--     } deriving (Generic, Show)
--   
--   instance FromForm Post
--   
-- --
--   >>> urlDecodeAsForm "comments=Nice%20post%21&comments=%2B1&title=Test" :: Either Text Post
--   Right (Post {title = "Test", subtitle = Nothing, comments = ["Nice post!","+1"]})
--   
genericFromForm :: forall a. (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a class GFromForm t (f :: * -> *) gFromForm :: GFromForm t f => Proxy t -> FormOptions -> Form -> Either Text (f x) -- | Encode a Form to an application/x-www-form-urlencoded -- ByteString. -- -- _NOTE:_ this encoding is unstable and may result in different key -- order (but not values). For a stable encoding see -- urlEncodeFormStable. urlEncodeForm :: Form -> ByteString -- | Encode a Form to an application/x-www-form-urlencoded -- ByteString. -- -- For an unstable (but faster) encoding see urlEncodeForm. -- -- Key-value pairs get encoded to key=value and separated by -- &: -- --
--   >>> urlEncodeFormStable [("name", "Julian"), ("lastname", "Arni")]
--   "lastname=Arni&name=Julian"
--   
-- -- Keys with empty values get encoded to just key (without the -- = sign): -- --
--   >>> urlEncodeFormStable [("is_test", "")]
--   "is_test"
--   
-- -- Empty keys are allowed too: -- --
--   >>> urlEncodeFormStable [("", "foobar")]
--   "=foobar"
--   
-- -- However, if both key and value are empty, the key-value pair is -- ignored. (This prevents urlDecodeForm . -- urlEncodeFormStable from being a true isomorphism). -- --
--   >>> urlEncodeFormStable [("", "")]
--   ""
--   
-- -- Everything is escaped with escapeURIString -- isUnreserved: -- --
--   >>> urlEncodeFormStable [("fullname", "Andres Löh")]
--   "fullname=Andres%20L%C3%B6h"
--   
urlEncodeFormStable :: Form -> ByteString -- | Encode a list of key-value pairs to an -- application/x-www-form-urlencoded ByteString. -- -- See also urlEncodeFormStable. urlEncodeParams :: [(Text, Text)] -> ByteString -- | Decode an application/x-www-form-urlencoded ByteString -- to a Form. -- -- Key-value pairs get decoded normally: -- --
--   >>> urlDecodeForm "name=Greg&lastname=Weber"
--   Right (fromList [("lastname","Weber"),("name","Greg")])
--   
-- -- Keys with no values get decoded to pairs with empty values. -- --
--   >>> urlDecodeForm "is_test"
--   Right (fromList [("is_test","")])
--   
-- -- Empty keys are allowed: -- --
--   >>> urlDecodeForm "=foobar"
--   Right (fromList [("","foobar")])
--   
-- -- The empty string gets decoded into an empty Form: -- --
--   >>> urlDecodeForm ""
--   Right (fromList [])
--   
-- -- Everything is un-escaped with unEscapeString: -- --
--   >>> urlDecodeForm "fullname=Andres%20L%C3%B6h"
--   Right (fromList [("fullname","Andres L\246h")])
--   
-- -- Improperly formed strings result in an error: -- --
--   >>> urlDecodeForm "this=has=too=many=equals"
--   Left "not a valid pair: this=has=too=many=equals"
--   
urlDecodeForm :: ByteString -> Either Text Form -- | Decode an application/x-www-form-urlencoded ByteString -- to a list of key-value pairs. -- -- See also urlDecodeForm. urlDecodeParams :: ByteString -> Either Text [(Text, Text)] -- | This is a convenience function for decoding a -- application/x-www-form-urlencoded ByteString directly -- to a datatype that has an instance of FromForm. -- -- This is effectively fromForm <=< -- urlDecodeForm. -- --
--   >>> urlDecodeAsForm "name=Dennis&age=22" :: Either Text Person
--   Right (Person {name = "Dennis", age = 22})
--   
urlDecodeAsForm :: FromForm a => ByteString -> Either Text a -- | This is a convenience function for encoding a datatype that has -- instance of ToForm directly to a -- application/x-www-form-urlencoded ByteString. -- -- This is effectively urlEncodeForm . toForm. -- -- _NOTE:_ this encoding is unstable and may result in different key -- order (but not values). For a stable encoding see -- urlEncodeAsFormStable. urlEncodeAsForm :: ToForm a => a -> ByteString -- | This is a convenience function for encoding a datatype that has -- instance of ToForm directly to a -- application/x-www-form-urlencoded ByteString. -- -- This is effectively urlEncodeFormStable . -- toForm. -- --
--   >>> urlEncodeAsFormStable Person {name = "Dennis", age = 22}
--   "age=22&name=Dennis"
--   
urlEncodeAsFormStable :: ToForm a => a -> ByteString -- | Find all values corresponding to a given key in a Form. -- --
--   >>> lookupAll "name" []
--   []
--   
--   >>> lookupAll "name" [("name", "Oleg")]
--   ["Oleg"]
--   
--   >>> lookupAll "name" [("name", "Oleg"), ("name", "David")]
--   ["Oleg","David"]
--   
lookupAll :: Text -> Form -> [Text] -- | Lookup an optional value for a key. Fail if there is more than one -- value. -- --
--   >>> lookupMaybe "name" []
--   Right Nothing
--   
--   >>> lookupMaybe "name" [("name", "Oleg")]
--   Right (Just "Oleg")
--   
--   >>> lookupMaybe "name" [("name", "Oleg"), ("name", "David")]
--   Left "Duplicate key \"name\""
--   
lookupMaybe :: Text -> Form -> Either Text (Maybe Text) -- | Lookup a unique value for a key. Fail if there is zero or more than -- one value. -- --
--   >>> lookupUnique "name" []
--   Left "Could not find key \"name\""
--   
--   >>> lookupUnique "name" [("name", "Oleg")]
--   Right "Oleg"
--   
--   >>> lookupUnique "name" [("name", "Oleg"), ("name", "David")]
--   Left "Duplicate key \"name\""
--   
lookupUnique :: Text -> Form -> Either Text Text -- | Lookup all values for a given key in a Form and parse them with -- parseQueryParams. -- --
--   >>> parseAll "age" [] :: Either Text [Word8]
--   Right []
--   
--   >>> parseAll "age" [("age", "8"), ("age", "seven")] :: Either Text [Word8]
--   Left "could not parse: `seven' (input does not start with a digit)"
--   
--   >>> parseAll "age" [("age", "8"), ("age", "777")] :: Either Text [Word8]
--   Left "out of bounds: `777' (should be between 0 and 255)"
--   
--   >>> parseAll "age" [("age", "12"), ("age", "25")] :: Either Text [Word8]
--   Right [12,25]
--   
parseAll :: FromHttpApiData v => Text -> Form -> Either Text [v] -- | Lookup an optional value for a given key and parse it with -- parseQueryParam. Fail if there is more than one value for the -- key. -- --
--   >>> parseMaybe "age" [] :: Either Text (Maybe Word8)
--   Right Nothing
--   
--   >>> parseMaybe "age" [("age", "12"), ("age", "25")] :: Either Text (Maybe Word8)
--   Left "Duplicate key \"age\""
--   
--   >>> parseMaybe "age" [("age", "seven")] :: Either Text (Maybe Word8)
--   Left "could not parse: `seven' (input does not start with a digit)"
--   
--   >>> parseMaybe "age" [("age", "777")] :: Either Text (Maybe Word8)
--   Left "out of bounds: `777' (should be between 0 and 255)"
--   
--   >>> parseMaybe "age" [("age", "7")] :: Either Text (Maybe Word8)
--   Right (Just 7)
--   
parseMaybe :: FromHttpApiData v => Text -> Form -> Either Text (Maybe v) -- | Lookup a unique value for a given key and parse it with -- parseQueryParam. Fail if there is zero or more than one value -- for the key. -- --
--   >>> parseUnique "age" [] :: Either Text Word8
--   Left "Could not find key \"age\""
--   
--   >>> parseUnique "age" [("age", "12"), ("age", "25")] :: Either Text Word8
--   Left "Duplicate key \"age\""
--   
--   >>> parseUnique "age" [("age", "seven")] :: Either Text Word8
--   Left "could not parse: `seven' (input does not start with a digit)"
--   
--   >>> parseUnique "age" [("age", "777")] :: Either Text Word8
--   Left "out of bounds: `777' (should be between 0 and 255)"
--   
--   >>> parseUnique "age" [("age", "7")] :: Either Text Word8
--   Right 7
--   
parseUnique :: FromHttpApiData v => Text -> Form -> Either Text v -- | Generic-based deriving options for ToForm and -- FromForm. -- -- A common use case for non-default FormOptions is to strip a -- prefix off of field labels: -- --
--   data Project = Project
--     { projectName :: String
--     , projectSize :: Int
--     } deriving (Generic, Show)
--   
--   myOptions :: FormOptions
--   myOptions = FormOptions
--    { fieldLabelModifier = map toLower . drop (length "project") }
--   
--   instance ToForm Project where
--     toForm = genericToForm myOptions
--   
--   instance FromForm Project where
--     fromForm = genericFromForm myOptions
--   
-- --
--   >>> urlEncodeAsFormStable Project { projectName = "http-api-data", projectSize = 172 }
--   "name=http-api-data&size=172"
--   
--   >>> urlDecodeAsForm "name=http-api-data&size=172" :: Either Text Project
--   Right (Project {projectName = "http-api-data", projectSize = 172})
--   
data FormOptions FormOptions :: (String -> String) -> FormOptions -- | Function applied to field labels. Handy for removing common record -- prefixes for example. [fieldLabelModifier] :: FormOptions -> String -> String -- | Default encoding FormOptions. -- --
--   FormOptions
--   { fieldLabelModifier = id
--   }
--   
defaultFormOptions :: FormOptions sortOn :: Ord b => (a -> b) -> [a] -> [a] instance GHC.Base.Monoid Web.Internal.FormUrlEncoded.Form instance Data.Semigroup.Semigroup Web.Internal.FormUrlEncoded.Form instance GHC.Generics.Generic Web.Internal.FormUrlEncoded.Form instance GHC.Read.Read Web.Internal.FormUrlEncoded.Form instance GHC.Classes.Eq Web.Internal.FormUrlEncoded.Form instance Web.Internal.FormUrlEncoded.ToForm Web.Internal.FormUrlEncoded.Form instance (Web.Internal.FormUrlEncoded.ToFormKey k, Web.Internal.HttpApiData.ToHttpApiData v) => Web.Internal.FormUrlEncoded.ToForm [(k, v)] instance (Web.Internal.FormUrlEncoded.ToFormKey k, Web.Internal.HttpApiData.ToHttpApiData v) => Web.Internal.FormUrlEncoded.ToForm (Data.Map.Internal.Map k [v]) instance (Web.Internal.FormUrlEncoded.ToFormKey k, Web.Internal.HttpApiData.ToHttpApiData v) => Web.Internal.FormUrlEncoded.ToForm (Data.HashMap.Base.HashMap k [v]) instance Web.Internal.HttpApiData.ToHttpApiData v => Web.Internal.FormUrlEncoded.ToForm (Data.IntMap.Internal.IntMap [v]) instance forall k (t :: k) (f :: * -> *) (g :: * -> *). Web.Internal.FormUrlEncoded.NotSupported Web.Internal.FormUrlEncoded.ToForm t "is a sum type" => Web.Internal.FormUrlEncoded.GToForm t (f GHC.Generics.:+: g) instance forall k (t :: k) (f :: * -> *) (g :: * -> *). (Web.Internal.FormUrlEncoded.GToForm t f, Web.Internal.FormUrlEncoded.GToForm t g) => Web.Internal.FormUrlEncoded.GToForm t (f GHC.Generics.:*: g) instance forall k (t :: k) (f :: * -> *) (x :: GHC.Generics.Meta). Web.Internal.FormUrlEncoded.GToForm t f => Web.Internal.FormUrlEncoded.GToForm t (GHC.Generics.M1 GHC.Generics.D x f) instance forall k (t :: k) (f :: * -> *) (x :: GHC.Generics.Meta). Web.Internal.FormUrlEncoded.GToForm t f => Web.Internal.FormUrlEncoded.GToForm t (GHC.Generics.M1 GHC.Generics.C x f) instance forall k (s :: GHC.Generics.Meta) c (t :: k) i. (GHC.Generics.Selector s, Web.Internal.HttpApiData.ToHttpApiData c) => Web.Internal.FormUrlEncoded.GToForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i c)) instance forall k (s :: GHC.Generics.Meta) c (t :: k) i. (GHC.Generics.Selector s, Web.Internal.HttpApiData.ToHttpApiData c) => Web.Internal.FormUrlEncoded.GToForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i (GHC.Base.Maybe c))) instance forall k (s :: GHC.Generics.Meta) c (t :: k) i. (GHC.Generics.Selector s, Web.Internal.HttpApiData.ToHttpApiData c) => Web.Internal.FormUrlEncoded.GToForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i [c])) instance forall k (s :: GHC.Generics.Meta) (t :: k) i. GHC.Generics.Selector s => Web.Internal.FormUrlEncoded.GToForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i GHC.Base.String)) instance Web.Internal.FormUrlEncoded.FromForm Web.Internal.FormUrlEncoded.Form instance (Web.Internal.FormUrlEncoded.FromFormKey k, Web.Internal.HttpApiData.FromHttpApiData v) => Web.Internal.FormUrlEncoded.FromForm [(k, v)] instance (GHC.Classes.Ord k, Web.Internal.FormUrlEncoded.FromFormKey k, Web.Internal.HttpApiData.FromHttpApiData v) => Web.Internal.FormUrlEncoded.FromForm (Data.Map.Internal.Map k [v]) instance (GHC.Classes.Eq k, Data.Hashable.Class.Hashable k, Web.Internal.FormUrlEncoded.FromFormKey k, Web.Internal.HttpApiData.FromHttpApiData v) => Web.Internal.FormUrlEncoded.FromForm (Data.HashMap.Base.HashMap k [v]) instance Web.Internal.HttpApiData.FromHttpApiData v => Web.Internal.FormUrlEncoded.FromForm (Data.IntMap.Internal.IntMap [v]) instance forall k (t :: k) (f :: * -> *) (g :: * -> *). Web.Internal.FormUrlEncoded.NotSupported Web.Internal.FormUrlEncoded.FromForm t "is a sum type" => Web.Internal.FormUrlEncoded.GFromForm t (f GHC.Generics.:+: g) instance forall k (t :: k) (f :: * -> *) (g :: * -> *). (Web.Internal.FormUrlEncoded.GFromForm t f, Web.Internal.FormUrlEncoded.GFromForm t g) => Web.Internal.FormUrlEncoded.GFromForm t (f GHC.Generics.:*: g) instance forall k (t :: k) (f :: * -> *) (x :: GHC.Generics.Meta). Web.Internal.FormUrlEncoded.GFromForm t f => Web.Internal.FormUrlEncoded.GFromForm t (GHC.Generics.M1 GHC.Generics.D x f) instance forall k (t :: k) (f :: * -> *) (x :: GHC.Generics.Meta). Web.Internal.FormUrlEncoded.GFromForm t f => Web.Internal.FormUrlEncoded.GFromForm t (GHC.Generics.M1 GHC.Generics.C x f) instance forall k (s :: GHC.Generics.Meta) c (t :: k) i. (GHC.Generics.Selector s, Web.Internal.HttpApiData.FromHttpApiData c) => Web.Internal.FormUrlEncoded.GFromForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i c)) instance forall k (s :: GHC.Generics.Meta) c (t :: k) i. (GHC.Generics.Selector s, Web.Internal.HttpApiData.FromHttpApiData c) => Web.Internal.FormUrlEncoded.GFromForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i (GHC.Base.Maybe c))) instance forall k (s :: GHC.Generics.Meta) c (t :: k) i. (GHC.Generics.Selector s, Web.Internal.HttpApiData.FromHttpApiData c) => Web.Internal.FormUrlEncoded.GFromForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i [c])) instance forall k (s :: GHC.Generics.Meta) (t :: k) i. GHC.Generics.Selector s => Web.Internal.FormUrlEncoded.GFromForm t (GHC.Generics.M1 GHC.Generics.S s (GHC.Generics.K1 i GHC.Base.String)) instance GHC.Show.Show Web.Internal.FormUrlEncoded.Form instance GHC.Exts.IsList Web.Internal.FormUrlEncoded.Form instance Web.Internal.FormUrlEncoded.FromFormKey () instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Char instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Bool instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Ordering instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Double instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Float instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Int instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Int.Int8 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Int.Int16 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Int.Int32 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Int.Int64 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Integer.Type.Integer instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Types.Word instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Word.Word8 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Word.Word16 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Word.Word32 instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Word.Word64 instance Web.Internal.FormUrlEncoded.FromFormKey Data.Time.Calendar.Days.Day instance Web.Internal.FormUrlEncoded.FromFormKey Data.Time.LocalTime.Internal.LocalTime.LocalTime instance Web.Internal.FormUrlEncoded.FromFormKey Data.Time.LocalTime.Internal.ZonedTime.ZonedTime instance Web.Internal.FormUrlEncoded.FromFormKey Data.Time.Clock.Internal.UTCTime.UTCTime instance Web.Internal.FormUrlEncoded.FromFormKey Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Base.String instance Web.Internal.FormUrlEncoded.FromFormKey Data.Text.Internal.Text instance Web.Internal.FormUrlEncoded.FromFormKey Data.Text.Internal.Lazy.Text instance Web.Internal.FormUrlEncoded.FromFormKey Data.Monoid.All instance Web.Internal.FormUrlEncoded.FromFormKey Data.Monoid.Any instance Web.Internal.FormUrlEncoded.FromFormKey a => Web.Internal.FormUrlEncoded.FromFormKey (Data.Monoid.Dual a) instance Web.Internal.FormUrlEncoded.FromFormKey a => Web.Internal.FormUrlEncoded.FromFormKey (Data.Monoid.Sum a) instance Web.Internal.FormUrlEncoded.FromFormKey a => Web.Internal.FormUrlEncoded.FromFormKey (Data.Monoid.Product a) instance Web.Internal.FormUrlEncoded.FromFormKey Data.Void.Void instance Web.Internal.FormUrlEncoded.FromFormKey GHC.Natural.Natural instance Web.Internal.FormUrlEncoded.ToFormKey () instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Char instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Bool instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Ordering instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Double instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Float instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Int instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Int.Int8 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Int.Int16 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Int.Int32 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Int.Int64 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Integer.Type.Integer instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Types.Word instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Word.Word8 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Word.Word16 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Word.Word32 instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Word.Word64 instance Web.Internal.FormUrlEncoded.ToFormKey Data.Time.Calendar.Days.Day instance Web.Internal.FormUrlEncoded.ToFormKey Data.Time.LocalTime.Internal.LocalTime.LocalTime instance Web.Internal.FormUrlEncoded.ToFormKey Data.Time.LocalTime.Internal.ZonedTime.ZonedTime instance Web.Internal.FormUrlEncoded.ToFormKey Data.Time.Clock.Internal.UTCTime.UTCTime instance Web.Internal.FormUrlEncoded.ToFormKey Data.Time.Clock.Internal.NominalDiffTime.NominalDiffTime instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Base.String instance Web.Internal.FormUrlEncoded.ToFormKey Data.Text.Internal.Text instance Web.Internal.FormUrlEncoded.ToFormKey Data.Text.Internal.Lazy.Text instance Web.Internal.FormUrlEncoded.ToFormKey Data.Monoid.All instance Web.Internal.FormUrlEncoded.ToFormKey Data.Monoid.Any instance Web.Internal.FormUrlEncoded.ToFormKey a => Web.Internal.FormUrlEncoded.ToFormKey (Data.Monoid.Dual a) instance Web.Internal.FormUrlEncoded.ToFormKey a => Web.Internal.FormUrlEncoded.ToFormKey (Data.Monoid.Sum a) instance Web.Internal.FormUrlEncoded.ToFormKey a => Web.Internal.FormUrlEncoded.ToFormKey (Data.Monoid.Product a) instance Web.Internal.FormUrlEncoded.ToFormKey Data.Void.Void instance Web.Internal.FormUrlEncoded.ToFormKey GHC.Natural.Natural -- | Convert Haskell values to and from -- application/xxx-form-urlencoded format. module Web.FormUrlEncoded -- | Convert a value into Form. -- -- An example type and instance: -- --
--   {-# LANGUAGE OverloadedLists #-}
--   
--   data Person = Person
--     { name :: String
--     , age  :: Int }
--   
--   instance ToForm Person where
--     toForm person =
--       [ ("name", toQueryParam (name person))
--       , ("age", toQueryParam (age person)) ]
--   
-- -- Instead of manually writing ToForm instances you can -- use a default generic implementation of toForm. -- -- To do that, simply add deriving Generic clause to your -- datatype and declare a ToForm instance for your datatype -- without giving definition for toForm. -- -- For instance, the previous example can be simplified into this: -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
--   instance ToForm Person
--   
-- -- The default implementation of toForm is genericToForm. class ToForm a -- | Convert a value into Form. toForm :: ToForm a => a -> Form -- | Convert a value into Form. toForm :: (ToForm a, Generic a, GToForm a (Rep a)) => a -> Form -- | Parse Form into a value. -- -- An example type and instance: -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int }
--   
--   instance FromForm Person where
--     fromForm f = Person
--       <$> parseUnique "name" f
--       <*> parseUnique "age"  f
--   
-- -- Instead of manually writing FromForm instances you can -- use a default generic implementation of fromForm. -- -- To do that, simply add deriving Generic clause to your -- datatype and declare a FromForm instance for your datatype -- without giving definition for fromForm. -- -- For instance, the previous example can be simplified into this: -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
--   instance FromForm Person
--   
-- -- The default implementation of fromForm is -- genericFromForm. It only works for records and it will use -- parseQueryParam for each field's value. class FromForm a -- | Parse Form into a value. fromForm :: FromForm a => Form -> Either Text a -- | Parse Form into a value. fromForm :: (FromForm a, Generic a, GFromForm a (Rep a)) => Form -> Either Text a -- | Typeclass for types that can be used as keys in a Form-like -- container (like Map). class ToFormKey k -- | Render a key for a Form. toFormKey :: ToFormKey k => k -> Text -- | Typeclass for types that can be parsed from keys of a Form. -- This is the reverse of ToFormKey. class FromFormKey k -- | Parse a key of a Form. parseFormKey :: FromFormKey k => Text -> Either Text k -- | The contents of a form, not yet URL-encoded. -- -- Form can be URL-encoded with urlEncodeForm and -- URL-decoded with urlDecodeForm. newtype Form Form :: HashMap Text [Text] -> Form [unForm] :: Form -> HashMap Text [Text] -- | This is a convenience function for encoding a datatype that has -- instance of ToForm directly to a -- application/x-www-form-urlencoded ByteString. -- -- This is effectively urlEncodeForm . toForm. -- -- _NOTE:_ this encoding is unstable and may result in different key -- order (but not values). For a stable encoding see -- urlEncodeAsFormStable. urlEncodeAsForm :: ToForm a => a -> ByteString -- | This is a convenience function for encoding a datatype that has -- instance of ToForm directly to a -- application/x-www-form-urlencoded ByteString. -- -- This is effectively urlEncodeFormStable . -- toForm. -- --
--   >>> urlEncodeAsFormStable Person {name = "Dennis", age = 22}
--   "age=22&name=Dennis"
--   
urlEncodeAsFormStable :: ToForm a => a -> ByteString -- | This is a convenience function for decoding a -- application/x-www-form-urlencoded ByteString directly -- to a datatype that has an instance of FromForm. -- -- This is effectively fromForm <=< -- urlDecodeForm. -- --
--   >>> urlDecodeAsForm "name=Dennis&age=22" :: Either Text Person
--   Right (Person {name = "Dennis", age = 22})
--   
urlDecodeAsForm :: FromForm a => ByteString -> Either Text a -- | Encode a Form to an application/x-www-form-urlencoded -- ByteString. -- -- _NOTE:_ this encoding is unstable and may result in different key -- order (but not values). For a stable encoding see -- urlEncodeFormStable. urlEncodeForm :: Form -> ByteString -- | Encode a Form to an application/x-www-form-urlencoded -- ByteString. -- -- For an unstable (but faster) encoding see urlEncodeForm. -- -- Key-value pairs get encoded to key=value and separated by -- &: -- --
--   >>> urlEncodeFormStable [("name", "Julian"), ("lastname", "Arni")]
--   "lastname=Arni&name=Julian"
--   
-- -- Keys with empty values get encoded to just key (without the -- = sign): -- --
--   >>> urlEncodeFormStable [("is_test", "")]
--   "is_test"
--   
-- -- Empty keys are allowed too: -- --
--   >>> urlEncodeFormStable [("", "foobar")]
--   "=foobar"
--   
-- -- However, if both key and value are empty, the key-value pair is -- ignored. (This prevents urlDecodeForm . -- urlEncodeFormStable from being a true isomorphism). -- --
--   >>> urlEncodeFormStable [("", "")]
--   ""
--   
-- -- Everything is escaped with escapeURIString -- isUnreserved: -- --
--   >>> urlEncodeFormStable [("fullname", "Andres Löh")]
--   "fullname=Andres%20L%C3%B6h"
--   
urlEncodeFormStable :: Form -> ByteString -- | Decode an application/x-www-form-urlencoded ByteString -- to a Form. -- -- Key-value pairs get decoded normally: -- --
--   >>> urlDecodeForm "name=Greg&lastname=Weber"
--   Right (fromList [("lastname","Weber"),("name","Greg")])
--   
-- -- Keys with no values get decoded to pairs with empty values. -- --
--   >>> urlDecodeForm "is_test"
--   Right (fromList [("is_test","")])
--   
-- -- Empty keys are allowed: -- --
--   >>> urlDecodeForm "=foobar"
--   Right (fromList [("","foobar")])
--   
-- -- The empty string gets decoded into an empty Form: -- --
--   >>> urlDecodeForm ""
--   Right (fromList [])
--   
-- -- Everything is un-escaped with unEscapeString: -- --
--   >>> urlDecodeForm "fullname=Andres%20L%C3%B6h"
--   Right (fromList [("fullname","Andres L\246h")])
--   
-- -- Improperly formed strings result in an error: -- --
--   >>> urlDecodeForm "this=has=too=many=equals"
--   Left "not a valid pair: this=has=too=many=equals"
--   
urlDecodeForm :: ByteString -> Either Text Form -- | A Generic-based implementation of toForm. This is used -- as a default implementation in ToForm. -- -- Note that this only works for records (i.e. product data types with -- named fields): -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
-- -- In this implementation each field's value gets encoded using -- toQueryParam. Two field types are exceptions: -- -- -- -- Here's an example: -- --
--   data Post = Post
--     { title    :: String
--     , subtitle :: Maybe String
--     , comments :: [String]
--     } deriving (Generic, Show)
--   
--   instance ToForm Post
--   
-- --
--   >>> urlEncodeAsFormStable Post { title = "Test", subtitle = Nothing, comments = ["Nice post!", "+1"] }
--   "comments=Nice%20post%21&comments=%2B1&title=Test"
--   
genericToForm :: forall a. (Generic a, GToForm a (Rep a)) => FormOptions -> a -> Form -- | A Generic-based implementation of fromForm. This is used -- as a default implementation in FromForm. -- -- Note that this only works for records (i.e. product data types with -- named fields): -- --
--   data Person = Person
--     { name :: String
--     , age  :: Int
--     } deriving (Generic)
--   
-- -- In this implementation each field's value gets decoded using -- parseQueryParam. Two field types are exceptions: -- -- -- -- Here's an example: -- --
--   data Post = Post
--     { title    :: String
--     , subtitle :: Maybe String
--     , comments :: [String]
--     } deriving (Generic, Show)
--   
--   instance FromForm Post
--   
-- --
--   >>> urlDecodeAsForm "comments=Nice%20post%21&comments=%2B1&title=Test" :: Either Text Post
--   Right (Post {title = "Test", subtitle = Nothing, comments = ["Nice post!","+1"]})
--   
genericFromForm :: forall a. (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a -- | Generic-based deriving options for ToForm and -- FromForm. -- -- A common use case for non-default FormOptions is to strip a -- prefix off of field labels: -- --
--   data Project = Project
--     { projectName :: String
--     , projectSize :: Int
--     } deriving (Generic, Show)
--   
--   myOptions :: FormOptions
--   myOptions = FormOptions
--    { fieldLabelModifier = map toLower . drop (length "project") }
--   
--   instance ToForm Project where
--     toForm = genericToForm myOptions
--   
--   instance FromForm Project where
--     fromForm = genericFromForm myOptions
--   
-- --
--   >>> urlEncodeAsFormStable Project { projectName = "http-api-data", projectSize = 172 }
--   "name=http-api-data&size=172"
--   
--   >>> urlDecodeAsForm "name=http-api-data&size=172" :: Either Text Project
--   Right (Project {projectName = "http-api-data", projectSize = 172})
--   
data FormOptions FormOptions :: (String -> String) -> FormOptions -- | Function applied to field labels. Handy for removing common record -- prefixes for example. [fieldLabelModifier] :: FormOptions -> String -> String -- | Default encoding FormOptions. -- --
--   FormOptions
--   { fieldLabelModifier = id
--   }
--   
defaultFormOptions :: FormOptions -- | A stable version of toList. toListStable :: Form -> [(Text, Text)] -- | Parse a Form into a list of entries groupped by key. -- -- _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])] -- | Parse a Form into a list of entries groupped by key. -- --
--   >>> toEntriesByKeyStable [("name", "Nick"), ("color", "red"), ("color", "white")] :: Either Text [(Text, [Text])]
--   Right [("color",["red","white"]),("name",["Nick"])]
--   
-- -- For an unstable (but faster) conversion see toEntriesByKey. toEntriesByKeyStable :: (Ord k, FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])] -- | Convert a list of entries groupped by key into a Form. -- --
--   >>> fromEntriesByKey [("name",["Nick"]),("color",["red","blue"])]
--   fromList [("color","red"),("color","blue"),("name","Nick")]
--   
fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form -- | Find all values corresponding to a given key in a Form. -- --
--   >>> lookupAll "name" []
--   []
--   
--   >>> lookupAll "name" [("name", "Oleg")]
--   ["Oleg"]
--   
--   >>> lookupAll "name" [("name", "Oleg"), ("name", "David")]
--   ["Oleg","David"]
--   
lookupAll :: Text -> Form -> [Text] -- | Lookup an optional value for a key. Fail if there is more than one -- value. -- --
--   >>> lookupMaybe "name" []
--   Right Nothing
--   
--   >>> lookupMaybe "name" [("name", "Oleg")]
--   Right (Just "Oleg")
--   
--   >>> lookupMaybe "name" [("name", "Oleg"), ("name", "David")]
--   Left "Duplicate key \"name\""
--   
lookupMaybe :: Text -> Form -> Either Text (Maybe Text) -- | Lookup a unique value for a key. Fail if there is zero or more than -- one value. -- --
--   >>> lookupUnique "name" []
--   Left "Could not find key \"name\""
--   
--   >>> lookupUnique "name" [("name", "Oleg")]
--   Right "Oleg"
--   
--   >>> lookupUnique "name" [("name", "Oleg"), ("name", "David")]
--   Left "Duplicate key \"name\""
--   
lookupUnique :: Text -> Form -> Either Text Text -- | Lookup all values for a given key in a Form and parse them with -- parseQueryParams. -- --
--   >>> parseAll "age" [] :: Either Text [Word8]
--   Right []
--   
--   >>> parseAll "age" [("age", "8"), ("age", "seven")] :: Either Text [Word8]
--   Left "could not parse: `seven' (input does not start with a digit)"
--   
--   >>> parseAll "age" [("age", "8"), ("age", "777")] :: Either Text [Word8]
--   Left "out of bounds: `777' (should be between 0 and 255)"
--   
--   >>> parseAll "age" [("age", "12"), ("age", "25")] :: Either Text [Word8]
--   Right [12,25]
--   
parseAll :: FromHttpApiData v => Text -> Form -> Either Text [v] -- | Lookup an optional value for a given key and parse it with -- parseQueryParam. Fail if there is more than one value for the -- key. -- --
--   >>> parseMaybe "age" [] :: Either Text (Maybe Word8)
--   Right Nothing
--   
--   >>> parseMaybe "age" [("age", "12"), ("age", "25")] :: Either Text (Maybe Word8)
--   Left "Duplicate key \"age\""
--   
--   >>> parseMaybe "age" [("age", "seven")] :: Either Text (Maybe Word8)
--   Left "could not parse: `seven' (input does not start with a digit)"
--   
--   >>> parseMaybe "age" [("age", "777")] :: Either Text (Maybe Word8)
--   Left "out of bounds: `777' (should be between 0 and 255)"
--   
--   >>> parseMaybe "age" [("age", "7")] :: Either Text (Maybe Word8)
--   Right (Just 7)
--   
parseMaybe :: FromHttpApiData v => Text -> Form -> Either Text (Maybe v) -- | Lookup a unique value for a given key and parse it with -- parseQueryParam. Fail if there is zero or more than one value -- for the key. -- --
--   >>> parseUnique "age" [] :: Either Text Word8
--   Left "Could not find key \"age\""
--   
--   >>> parseUnique "age" [("age", "12"), ("age", "25")] :: Either Text Word8
--   Left "Duplicate key \"age\""
--   
--   >>> parseUnique "age" [("age", "seven")] :: Either Text Word8
--   Left "could not parse: `seven' (input does not start with a digit)"
--   
--   >>> parseUnique "age" [("age", "777")] :: Either Text Word8
--   Left "out of bounds: `777' (should be between 0 and 255)"
--   
--   >>> parseUnique "age" [("age", "7")] :: Either Text Word8
--   Right 7
--   
parseUnique :: FromHttpApiData v => Text -> Form -> Either Text v -- | Encode a list of key-value pairs to an -- application/x-www-form-urlencoded ByteString. -- -- See also urlEncodeFormStable. urlEncodeParams :: [(Text, Text)] -> ByteString -- | Decode an application/x-www-form-urlencoded ByteString -- to a list of key-value pairs. -- -- See also urlDecodeForm. urlDecodeParams :: ByteString -> Either Text [(Text, Text)] -- | Convert Haskell values to and from HTTP API data such as URL pieces, -- headers and query parameters. module Web.HttpApiData -- | Convert value to HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class ToHttpApiData a -- | Convert to URL path piece. toUrlPiece :: ToHttpApiData a => a -> Text -- | Convert to a URL path piece, making sure to encode any special chars. -- The default definition uses encodePathSegmentsRelative, but -- this may be overriden with a more efficient version. toEncodedUrlPiece :: ToHttpApiData a => a -> Builder -- | Convert to HTTP header value. toHeader :: ToHttpApiData a => a -> ByteString -- | Convert to query param value. toQueryParam :: ToHttpApiData a => a -> Text -- | Parse value from HTTP API data. -- -- WARNING: Do not derive this using DeriveAnyClass as -- the generated instance will loop indefinitely. class FromHttpApiData a -- | Parse URL path piece. parseUrlPiece :: FromHttpApiData a => Text -> Either Text a -- | Parse HTTP header value. parseHeader :: FromHttpApiData a => ByteString -> Either Text a -- | Parse query param value. parseQueryParam :: FromHttpApiData a => Text -> Either Text a -- | Parse URL path piece in a Maybe. -- --
--   >>> parseUrlPieceMaybe "12" :: Maybe Int
--   Just 12
--   
parseUrlPieceMaybe :: FromHttpApiData a => Text -> Maybe a -- | Parse HTTP header value in a Maybe. -- --
--   >>> parseHeaderMaybe "hello" :: Maybe Text
--   Just "hello"
--   
parseHeaderMaybe :: FromHttpApiData a => ByteString -> Maybe a -- | Parse query param value in a Maybe. -- --
--   >>> parseQueryParamMaybe "true" :: Maybe Bool
--   Just True
--   
parseQueryParamMaybe :: FromHttpApiData a => Text -> Maybe a -- | Case insensitive. -- -- Parse given text case insensitive and then parse the rest of the input -- using parseUrlPiece. -- --
--   >>> parseUrlPieceWithPrefix "Just " "just 10" :: Either Text Int
--   Right 10
--   
--   >>> parseUrlPieceWithPrefix "Left " "left" :: Either Text Bool
--   Left "could not parse: `left'"
--   
-- -- This can be used to implement FromHttpApiData for -- single field constructors: -- --
--   >>> data Foo = Foo Int deriving (Show)
--   
--   >>> instance FromHttpApiData Foo where parseUrlPiece s = Foo <$> parseUrlPieceWithPrefix "Foo " s
--   
--   >>> parseUrlPiece "foo 1" :: Either Text Foo
--   Right (Foo 1)
--   
parseUrlPieceWithPrefix :: FromHttpApiData a => Text -> Text -> Either Text a -- | Parse given bytestring then parse the rest of the input using -- parseHeader. -- --
--   data BasicAuthToken = BasicAuthToken Text deriving (Show)
--   
--   instance FromHttpApiData BasicAuthToken where
--     parseHeader h     = BasicAuthToken <$> parseHeaderWithPrefix "Basic " h
--     parseQueryParam p = BasicAuthToken <$> parseQueryParam p
--   
-- --
--   >>> parseHeader "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" :: Either Text BasicAuthToken
--   Right (BasicAuthToken "QWxhZGRpbjpvcGVuIHNlc2FtZQ==")
--   
parseHeaderWithPrefix :: FromHttpApiData a => ByteString -> ByteString -> Either Text a -- | Case insensitive. -- -- Parse given text case insensitive and then parse the rest of the input -- using parseQueryParam. -- --
--   >>> parseQueryParamWithPrefix "z" "z10" :: Either Text Int
--   Right 10
--   
parseQueryParamWithPrefix :: FromHttpApiData a => Text -> Text -> Either Text a -- | Convert multiple values to a list of URL pieces. -- --
--   >>> toUrlPieces [1, 2, 3] :: [Text]
--   ["1","2","3"]
--   
toUrlPieces :: (Functor t, ToHttpApiData a) => t a -> t Text -- | Parse multiple URL pieces. -- --
--   >>> parseUrlPieces ["true", "false"] :: Either Text [Bool]
--   Right [True,False]
--   
--   >>> parseUrlPieces ["123", "hello", "world"] :: Either Text [Int]
--   Left "could not parse: `hello' (input does not start with a digit)"
--   
parseUrlPieces :: (Traversable t, FromHttpApiData a) => t Text -> Either Text (t a) -- | Convert multiple values to a list of query parameter values. -- --
--   >>> toQueryParams [fromGregorian 2015 10 03, fromGregorian 2015 12 01] :: [Text]
--   ["2015-10-03","2015-12-01"]
--   
toQueryParams :: (Functor t, ToHttpApiData a) => t a -> t Text -- | Parse multiple query parameters. -- --
--   >>> parseQueryParams ["1", "2", "3"] :: Either Text [Int]
--   Right [1,2,3]
--   
--   >>> parseQueryParams ["64", "128", "256"] :: Either Text [Word8]
--   Left "out of bounds: `256' (should be between 0 and 255)"
--   
parseQueryParams :: (Traversable t, FromHttpApiData a) => t Text -> Either Text (t a) -- | Case insensitive. -- -- Parse values case insensitively based on ToHttpApiData -- instance. Uses toUrlPiece to get possible values. parseBoundedUrlPiece :: (ToHttpApiData a, Bounded a, Enum a) => Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on ToHttpApiData -- instance. Uses toQueryParam to get possible values. parseBoundedQueryParam :: (ToHttpApiData a, Bounded a, Enum a) => Text -> Either Text a -- | Parse values based on ToHttpApiData instance. Uses -- toHeader to get possible values. parseBoundedHeader :: (ToHttpApiData a, Bounded a, Enum a) => ByteString -> Either Text a -- | Parse values based on a precalculated mapping of their -- Text representation. -- --
--   >>> parseBoundedEnumOf toUrlPiece "true" :: Either Text Bool
--   Right True
--   
-- -- For case sensitive parser see parseBoundedEnumOfI. parseBoundedEnumOf :: (Bounded a, Enum a) => (a -> Text) -> Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on a precalculated mapping of -- their Text representations. -- --
--   >>> parseBoundedEnumOfI toUrlPiece "FALSE" :: Either Text Bool
--   Right False
--   
-- -- For case sensitive parser see parseBoundedEnumOf. parseBoundedEnumOfI :: (Bounded a, Enum a) => (a -> Text) -> Text -> Either Text a -- | Case insensitive. -- -- Parse values case insensitively based on Show -- instance. -- --
--   >>> parseBoundedTextData "true" :: Either Text Bool
--   Right True
--   
--   >>> parseBoundedTextData "FALSE" :: Either Text Bool
--   Right False
--   
-- -- This can be used as a default implementation for enumeration types: -- --
--   >>> data MyData = Foo | Bar | Baz deriving (Show, Bounded, Enum)
--   
--   >>> instance FromHttpApiData MyData where parseUrlPiece = parseBoundedTextData
--   
--   >>> parseUrlPiece "foo" :: Either Text MyData
--   Right Foo
--   
parseBoundedTextData :: (Show a, Bounded a, Enum a) => Text -> Either Text a -- | Lenient parameters. FromHttpApiData combinators always return -- Right. newtype LenientData a LenientData :: Either Text a -> LenientData a [getLenientData] :: LenientData a -> Either Text a -- | Lower case. -- -- Convert to URL piece using Show instance. The result -- is always lower cased. -- --
--   >>> showTextData True
--   "true"
--   
-- -- This can be used as a default implementation for enumeration types: -- --
--   >>> data MyData = Foo | Bar | Baz deriving (Show)
--   
--   >>> instance ToHttpApiData MyData where toUrlPiece = showTextData
--   
--   >>> toUrlPiece Foo
--   "foo"
--   
showTextData :: Show a => a -> Text -- | Parse URL piece using Read instance. -- -- Use for types which do not involve letters: -- --
--   >>> readTextData "1991-06-02" :: Either Text Day
--   Right 1991-06-02
--   
-- -- This parser is case sensitive and will not match -- showTextData in presence of letters: -- --
--   >>> readTextData (showTextData True) :: Either Text Bool
--   Left "could not parse: `true'"
--   
-- -- See parseBoundedTextData. readTextData :: Read a => Text -> Either Text a