http-api-data-0.6.1: Converting to/from HTTP API data like URL pieces, headers and query parameters.

Safe Haskell | None
Language | Haskell2010

Web.Internal.FormUrlEncoded

Synopsis

- class ToFormKey k where
  - toFormKey :: k -> Text
- class FromFormKey k where
  - parseFormKey :: Text -> Either Text k
- newtype Form = Form {
  - unForm :: HashMap Text [Text]
  }
- toListStable :: Form -> [(Text, Text)]
- class ToForm a where
  - toForm :: a -> Form
- fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> Form
- data Proxy3 (a :: k) (b :: k1) (c :: k2) = Proxy3
- type family NotSupported (cls :: k1) (a :: k2) (reason :: Symbol) where ...
- genericToForm :: (Generic a, GToForm a (Rep a)) => FormOptions -> a -> Form
- class GToForm (t :: k) (f :: Type -> Type) where
  - gToForm :: Proxy t -> FormOptions -> f x -> Form
- class FromForm a where
  - fromForm :: Form -> Either Text a
- toEntriesByKey :: (FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]
- toEntriesByKeyStable :: (Ord k, FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])]
- genericFromForm :: (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a
- class GFromForm (t :: k) (f :: Type -> Type) where
  - gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (f x)
- urlEncodeForm :: Form -> ByteString
- urlEncodeFormStable :: Form -> ByteString
- urlEncodeParams :: [(Text, Text)] -> ByteString
- urlDecodeForm :: ByteString -> Either Text Form
- urlDecodeParams :: ByteString -> Either Text [(Text, Text)]
- urlDecodeAsForm :: FromForm a => ByteString -> Either Text a
- urlEncodeAsForm :: ToForm a => a -> ByteString
- urlEncodeAsFormStable :: ToForm a => a -> ByteString
- lookupAll :: Text -> Form -> [Text]
- lookupMaybe :: Text -> Form -> Either Text (Maybe Text)
- lookupUnique :: Text -> Form -> Either Text Text
- parseAll :: FromHttpApiData v => Text -> Form -> Either Text [v]
- parseMaybe :: FromHttpApiData v => Text -> Form -> Either Text (Maybe v)
- parseUnique :: FromHttpApiData v => Text -> Form -> Either Text v
- data FormOptions = FormOptions {
  - fieldLabelModifier :: String -> String
  }
- defaultFormOptions :: FormOptions
- sortOn :: Ord b => (a -> b) -> [a] -> [a]

# Documentation

    >>> :set -XDeriveGeneric -XOverloadedLists -XOverloadedStrings -XFlexibleContexts -XScopedTypeVariables -XTypeFamilies
    >>> import GHC.Generics (Generic)
    >>> import Data.Char (toLower)
    >>> import Data.Text (Text)
    >>> import Data.Word (Word8)

    >>> data Person = Person { name :: String, age :: Int } deriving (Show, Generic)
    >>> instance ToForm Person
    >>> instance FromForm Person

    >>> data Post = Post { title :: String, subtitle :: Maybe String, comments :: [String]} deriving (Generic, Show)
    >>> instance ToForm Post
    >>> instance FromForm Post

    >>> data Project = Project { projectName :: String, projectSize :: Int } deriving (Generic, Show)
    >>> let myOptions = FormOptions { fieldLabelModifier = map toLower . drop (length ("project" :: String)) }
    >>> instance ToForm Project where toForm = genericToForm myOptions
    >>> instance FromForm Project where fromForm = genericFromForm myOptions

class ToFormKey k where #

Typeclass for types that can be used as keys in a `Form`-like container (like `Map`).

Methods

toFormKey :: k -> Text #

Render a key for a `Form`.

#### Instances

Instances details

ToFormKey Void # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Void -> Text #
ToFormKey All # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: All -> Text #
ToFormKey Any # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Any -> Text #
ToFormKey Int16 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Int16 -> Text #
ToFormKey Int32 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Int32 -> Text #
ToFormKey Int64 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Int64 -> Text #
ToFormKey Int8 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Int8 -> Text #
ToFormKey Word16 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Word16 -> Text #
ToFormKey Word32 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Word32 -> Text #
ToFormKey Word64 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Word64 -> Text #
ToFormKey Word8 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Word8 -> Text #
ToFormKey Ordering # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Ordering -> Text #
ToFormKey Text # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Text -> Text #
ToFormKey Text # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Text -> Text #
ToFormKey Day # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Day -> Text #
ToFormKey Month # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Month -> Text #
ToFormKey Quarter # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Quarter -> Text #
ToFormKey QuarterOfYear # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: QuarterOfYear -> Text #
ToFormKey NominalDiffTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: NominalDiffTime -> Text #
ToFormKey UTCTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: UTCTime -> Text #
ToFormKey LocalTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: LocalTime -> Text #
ToFormKey ZonedTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: ZonedTime -> Text #
ToFormKey Integer # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Integer -> Text #
ToFormKey Natural # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Natural -> Text #
ToFormKey String # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: String -> Text #
ToFormKey () # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: () -> Text #
ToFormKey Bool # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Bool -> Text #
ToFormKey Char # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Char -> Text #
ToFormKey Double # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Double -> Text #
ToFormKey Float # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Float -> Text #
ToFormKey Int # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Int -> Text #
ToFormKey Word # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Word -> Text #
ToFormKey a => ToFormKey (First a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: First a -> Text #
ToFormKey a => ToFormKey (Last a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Last a -> Text #
ToFormKey a => ToFormKey (Max a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Max a -> Text #
ToFormKey a => ToFormKey (Min a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Min a -> Text #
ToFormKey a => ToFormKey (Identity a) # | Since: 0.4.2
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Identity a -> Text #
ToFormKey a => ToFormKey (Dual a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Dual a -> Text #
ToFormKey a => ToFormKey (Product a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Product a -> Text #
ToFormKey a => ToFormKey (Sum a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Sum a -> Text #
ToFormKey a => ToFormKey (Const a b) # | Since: 0.4.2
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Const a b -> Text #
ToFormKey a => ToFormKey (Tagged b a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toFormKey :: Tagged b a -> Text #

class FromFormKey k where #

Typeclass for types that can be parsed from keys of a `Form`. This is the reverse of `ToFormKey`.

Methods

parseFormKey :: Text -> Either Text k #

Parse a key of a `Form`.

#### Instances

Instances details

FromFormKey Void # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Void #
FromFormKey All # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text All #
FromFormKey Any # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Any #
FromFormKey Int16 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Int16 #
FromFormKey Int32 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Int32 #
FromFormKey Int64 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Int64 #
FromFormKey Int8 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Int8 #
FromFormKey Word16 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Word16 #
FromFormKey Word32 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Word32 #
FromFormKey Word64 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Word64 #
FromFormKey Word8 # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Word8 #
FromFormKey Ordering # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Ordering #
FromFormKey Text # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Text #
FromFormKey Text # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Text #
FromFormKey Day # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Day #
FromFormKey Month # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Month #
FromFormKey Quarter # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Quarter #
FromFormKey QuarterOfYear # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text QuarterOfYear #
FromFormKey NominalDiffTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text NominalDiffTime #
FromFormKey UTCTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text UTCTime #
FromFormKey LocalTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text LocalTime #
FromFormKey ZonedTime # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text ZonedTime #
FromFormKey Integer # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Integer #
FromFormKey Natural # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Natural #
FromFormKey String # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text String #
FromFormKey () # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text () #
FromFormKey Bool # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Bool #
FromFormKey Char # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Char #
FromFormKey Double # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Double #
FromFormKey Float # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Float #
FromFormKey Int # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Int #
FromFormKey Word # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text Word #
FromFormKey a => FromFormKey (First a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (First a) #
FromFormKey a => FromFormKey (Last a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Last a) #
FromFormKey a => FromFormKey (Max a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Max a) #
FromFormKey a => FromFormKey (Min a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Min a) #
FromFormKey a => FromFormKey (Identity a) # | Since: 0.4.2
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Identity a) #
FromFormKey a => FromFormKey (Dual a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Dual a) #
FromFormKey a => FromFormKey (Product a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Product a) #
FromFormKey a => FromFormKey (Sum a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Sum a) #
FromFormKey a => FromFormKey (Const a b) # | Since: 0.4.2
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Const a b) #
FromFormKey a => FromFormKey (Tagged b a) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods parseFormKey :: Text -> Either Text (Tagged b a) #

newtype Form #

The contents of a form, not yet URL-encoded.

`Form` can be URL-encoded with `urlEncodeForm` and URL-decoded with `urlDecodeForm`.

Constructors

Form |
Fields unForm :: HashMap Text [Text]

#### Instances

Instances details

Monoid Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods mempty :: Form # mappend :: Form -> Form -> Form # mconcat :: [Form] -> Form #
Semigroup Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods (<>) :: Form -> Form -> Form # sconcat :: NonEmpty Form -> Form # stimes :: Integral b => b -> Form -> Form #
Generic Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Associated Types
type Rep Form |
Instance details Defined in Web.Internal.FormUrlEncoded type Rep Form = D1 ('MetaData "Form" "Web.Internal.FormUrlEncoded" "http-api-data-0.6.1-AlO8H4gUl4VFCeAOj9iYfz" 'True) (C1 ('MetaCons "Form" 'PrefixI 'True) (S1 ('MetaSel ('Just "unForm") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (HashMap Text [Text]))))
Methods from :: Form -> Rep Form x # to :: Rep Form x -> Form #
IsList Form # | _NOTE:_ `toList` is unstable and may result in different key order (but not values). For a stable conversion use `toListStable`.
Instance details Defined in Web.Internal.FormUrlEncoded Associated Types
type Item Form |
Instance details Defined in Web.Internal.FormUrlEncoded type Item Form = (Text, Text)
Methods fromList :: [Item Form] -> Form # fromListN :: Int -> [Item Form] -> Form # toList :: Form -> [Item Form] #
Read Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods readsPrec :: Int -> ReadS Form # readList :: ReadS [Form] # readPrec :: ReadPrec Form # readListPrec :: ReadPrec [Form] #
Show Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods showsPrec :: Int -> Form -> ShowS # show :: Form -> String # showList :: [Form] -> ShowS #
Eq Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods (==) :: Form -> Form -> Bool # (/=) :: Form -> Form -> Bool #
FromForm Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods fromForm :: Form -> Either Text Form #
ToForm Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toForm :: Form -> Form #
type Rep Form # |
Instance details Defined in Web.Internal.FormUrlEncoded type Rep Form = D1 ('MetaData "Form" "Web.Internal.FormUrlEncoded" "http-api-data-0.6.1-AlO8H4gUl4VFCeAOj9iYfz" 'True) (C1 ('MetaCons "Form" 'PrefixI 'True) (S1 ('MetaSel ('Just "unForm") 'NoSourceUnpackedness 'NoSourceStrictness 'DecidedLazy) (Rec0 (HashMap Text [Text]))))
type Item Form # |
Instance details Defined in Web.Internal.FormUrlEncoded type Item Form = (Text, Text)

toListStable :: Form -> [(Text, Text)] #

A stable version of `toList`.

class ToForm a where #

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

Minimal complete definition

Nothing

Methods

toForm :: a -> Form #

Convert a value into `Form`.

default toForm :: (Generic a, GToForm a (Rep a)) => a -> Form #

#### Instances

Instances details

ToForm Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toForm :: Form -> Form #
ToHttpApiData v => ToForm (IntMap [v]) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toForm :: IntMap [v] -> Form #
(ToFormKey k, ToHttpApiData v) => ToForm [(k, v)] # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toForm :: [(k, v)] -> Form #
(ToFormKey k, ToHttpApiData v) => ToForm (Map k [v]) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toForm :: Map k [v] -> Form #
(ToFormKey k, ToHttpApiData v) => ToForm (HashMap k [v]) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods toForm :: HashMap k [v] -> Form #

fromEntriesByKey :: (ToFormKey k, ToHttpApiData v) => [(k, [v])] -> 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")]

data Proxy3 (a :: k) (b :: k1) (c :: k2) #

Constructors

Proxy3 |

type family NotSupported (cls :: k1) (a :: k2) (reason :: Symbol) where ... #

Equations

NotSupported (cls :: t1) (a :: t2) reason = TypeError ((((((('Text "Cannot derive a Generic-based " ':<>: 'ShowType cls) ':<>: 'Text " instance for ") ':<>: 'ShowType a) ':<>: 'Text ".") ':$$: ((('ShowType a ':<>: 'Text " ") ':<>: 'Text reason) ':<>: 'Text ",")) ':$$: (('Text "but Generic-based " ':<>: 'ShowType cls) ':<>: 'Text " instances can be derived only for records")) ':$$: 'Text "(i.e. product types with named fields).") :: Constraint |

genericToForm :: (Generic a, GToForm a (Rep a)) => FormOptions -> a -> 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:

- for values of type ``Maybe` a` an entry is added to the `Form` only when it is ``Just` x` and the encoded value is ``toQueryParam` x`; `Nothing` values are omitted from the `Form`;
- for values of type `[a]` (except `[`Char`]`) an entry is added for every item in the list; if the list is empty no entries are added to the `Form`;

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"

class GToForm (t :: k) (f :: Type -> Type) where #

Methods

gToForm :: Proxy t -> FormOptions -> f x -> Form #

#### Instances

Instances details

(GToForm t f, GToForm t g) => GToForm (t :: k) (f :*: g) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> (f :*: g) x -> Form #
NotSupported ToForm t "is a sum type" => GToForm (t :: k) (f :+: g) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> (f :+: g) x -> Form #
GToForm t f => GToForm (t :: k) (M1 C x f) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> M1 C x f x0 -> Form #
GToForm t f => GToForm (t :: k) (M1 D x f) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> M1 D x f x0 -> Form #
Selector s => GToForm (t :: k) (M1 S s (K1 i String :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> M1 S s (K1 i String :: Type -> Type) x -> Form #
(Selector s, ToHttpApiData c) => GToForm (t :: k) (M1 S s (K1 i (Maybe c) :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> M1 S s (K1 i (Maybe c) :: Type -> Type) x -> Form #
(Selector s, ToHttpApiData c) => GToForm (t :: k) (M1 S s (K1 i [c] :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> M1 S s (K1 i [c] :: Type -> Type) x -> Form #
(Selector s, ToHttpApiData c) => GToForm (t :: k) (M1 S s (K1 i c :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gToForm :: Proxy t -> FormOptions -> M1 S s (K1 i c :: Type -> Type) x -> Form #

class FromForm a where #

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.

Minimal complete definition

Nothing

Methods

fromForm :: Form -> Either Text a #

Parse `Form` into a value.

default fromForm :: (Generic a, GFromForm a (Rep a)) => Form -> Either Text a #

#### Instances

Instances details

FromForm Form # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods fromForm :: Form -> Either Text Form #
FromHttpApiData v => FromForm (IntMap [v]) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods fromForm :: Form -> Either Text (IntMap [v]) #
(FromFormKey k, FromHttpApiData v) => FromForm [(k, v)] # | _NOTE:_ this conversion is unstable and may result in different key order (but not values).
Instance details Defined in Web.Internal.FormUrlEncoded Methods fromForm :: Form -> Either Text [(k, v)] #
(Ord k, FromFormKey k, FromHttpApiData v) => FromForm (Map k [v]) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods fromForm :: Form -> Either Text (Map k [v]) #
(Eq k, Hashable k, FromFormKey k, FromHttpApiData v) => FromForm (HashMap k [v]) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods fromForm :: Form -> Either Text (HashMap k [v]) #

toEntriesByKey :: (FromFormKey k, FromHttpApiData v) => Form -> Either Text [(k, [v])] #

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

toEntriesByKeyStable :: (Ord k, 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`.

genericFromForm :: (Generic a, GFromForm a (Rep a)) => FormOptions -> Form -> Either Text a #

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:

- for values of type ``Maybe` a` an entry is parsed if present in the `Form` and the is decoded with `parseQueryParam`; if no entry is present result is `Nothing`;
- for values of type `[a]` (except `[`Char`]`) all entries are parsed to produce a list of parsed values;

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"]})

class GFromForm (t :: k) (f :: Type -> Type) where #

Methods

gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (f x) #

#### Instances

Instances details

(GFromForm t f, GFromForm t g) => GFromForm (t :: k) (f :*: g) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text ((f :*: g) x) #
NotSupported FromForm t "is a sum type" => GFromForm (t :: k) (f :+: g) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text ((f :+: g) x) #
GFromForm t f => GFromForm (t :: k) (M1 C x f) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (M1 C x f x0) #
GFromForm t f => GFromForm (t :: k) (M1 D x f) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (M1 D x f x0) #
Selector s => GFromForm (t :: k) (M1 S s (K1 i String :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (M1 S s (K1 i String :: Type -> Type) x) #
(Selector s, FromHttpApiData c) => GFromForm (t :: k) (M1 S s (K1 i (Maybe c) :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (M1 S s (K1 i (Maybe c) :: Type -> Type) x) #
(Selector s, FromHttpApiData c) => GFromForm (t :: k) (M1 S s (K1 i [c] :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (M1 S s (K1 i [c] :: Type -> Type) x) #
(Selector s, FromHttpApiData c) => GFromForm (t :: k) (M1 S s (K1 i c :: Type -> Type)) # |
Instance details Defined in Web.Internal.FormUrlEncoded Methods gFromForm :: Proxy t -> FormOptions -> Form -> Either Text (M1 S s (K1 i c :: Type -> Type) x) #

urlEncodeForm :: Form -> ByteString #

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

urlEncodeFormStable :: 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"

urlEncodeParams :: [(Text, Text)] -> ByteString #

Encode a list of key-value pairs to an `application/x-www-form-urlencoded` `ByteString`.

See also `urlEncodeFormStable`.

urlDecodeForm :: ByteString -> Either Text Form #

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"

urlDecodeParams :: ByteString -> Either Text [(Text, Text)] #

Decode an `application/x-www-form-urlencoded` `ByteString` to a list of key-value pairs.

See also `urlDecodeForm`.

urlDecodeAsForm :: FromForm a => ByteString -> Either Text a #

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

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 ``urlEncodeForm` . `toForm``.

_NOTE:_ this encoding is unstable and may result in different key order (but not values). For a stable encoding see `urlEncodeAsFormStable`.

urlEncodeAsFormStable :: 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"

lookupAll :: Text -> Form -> [Text] #

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

lookupMaybe :: Text -> Form -> Either Text (Maybe 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\""

lookupUnique :: Text -> Form -> Either Text 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\""

parseAll :: FromHttpApiData v => Text -> Form -> Either Text [v] #

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]

parseMaybe :: FromHttpApiData v => Text -> Form -> Either Text (Maybe 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)

parseUnique :: FromHttpApiData v => Text -> Form -> Either Text 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

data FormOptions #

`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})

Constructors

FormOptions |
Fields fieldLabelModifier :: String -> String Function applied to field labels. Handy for removing common record prefixes for example.

defaultFormOptions :: FormOptions #

Default encoding `FormOptions`.

    FormOptions
    { fieldLabelModifier = id
    }

sortOn :: Ord b => (a -> b) -> [a] -> [a] #