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

Safe HaskellNone
LanguageHaskell2010

Web.HttpApiData

Contents

Description

Convert Haskell values to and from HTTP API data such as URL pieces, headers and query parameters.

Synopsis

Examples

Booleans:

>>> toUrlPiece True
"true"
>>> parseUrlPiece "false" :: Either Text Bool
Right False
>>> parseUrlPieces ["true", "false", "undefined"] :: Either Text [Bool]
Left "could not parse: `undefined'"

Numbers:

>>> toQueryParam 45.2
"45.2"
>>> parseQueryParam "452" :: Either Text Int
Right 452
>>> toQueryParams [1..5] :: [Text]
["1","2","3","4","5"]
>>> parseQueryParams ["127", "255"] :: Either Text [Int8]
Left "out of bounds: `255' (should be between -128 and 127)"

Strings:

>>> toHeader "hello"
"hello"
>>> parseHeader "world" :: Either Text String
Right "world"

Calendar day:

>>> toQueryParam (fromGregorian 2015 10 03)
"2015-10-03"
>>> toGregorian <$> parseQueryParam "2016-12-01"
Right (2016,12,1)

Classes

class ToHttpApiData a where Source #

Convert value to HTTP API data.

WARNING: Do not derive this using DeriveAnyClass as the generated instance will loop indefinitely.

Minimal complete definition

toUrlPiece | toQueryParam

Methods

toUrlPiece :: a -> Text Source #

Convert to URL path piece.

toEncodedUrlPiece :: a -> Builder Source #

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.

toHeader :: a -> ByteString Source #

Convert to HTTP header value.

toQueryParam :: a -> Text Source #

Convert to query param value.

Instances
ToHttpApiData Bool Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Char Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Double Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Float Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Int Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Int8 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Int16 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Int32 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Int64 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Integer Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Natural Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Ordering Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Word Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Word8 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Word16 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Word32 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Word64 Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData () Source #
>>> toUrlPiece ()
"_"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Text Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Text Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData String Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Void Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Version Source #
>>> toUrlPiece (Version [1, 2, 3] [])
"1.2.3"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData All Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Any Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData UTCTime Source #
>>> toUrlPiece $ UTCTime (fromGregorian 2015 10 03) 864.5
"2015-10-03T00:14:24.5Z"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData SetCookie Source #

Note: this instance works correctly for alphanumeric name and value

>>> let Right c = parseUrlPiece "SESSID=r2t5uvjq435r4q7ib3vtdjq120" :: Either Text SetCookie
>>> toUrlPiece c
"SESSID=r2t5uvjq435r4q7ib3vtdjq120"
>>> toHeader c
"SESSID=r2t5uvjq435r4q7ib3vtdjq120"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData ZonedTime Source #
>>> toUrlPiece $ ZonedTime (LocalTime (fromGregorian 2015 10 03) (TimeOfDay 14 55 51.001)) utc
"2015-10-03T14:55:51.001+0000"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData LocalTime Source #
>>> toUrlPiece $ LocalTime (fromGregorian 2015 10 03) (TimeOfDay 14 55 21.687)
"2015-10-03T14:55:21.687"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData TimeOfDay Source #
>>> toUrlPiece $ TimeOfDay 14 55 23.1
"14:55:23.1"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData NominalDiffTime Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData Day Source #
>>> toUrlPiece (fromGregorian 2015 10 03)
"2015-10-03"
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData UUID Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData a => ToHttpApiData (Maybe a) Source #
>>> toUrlPiece (Just "Hello")
"just Hello"
Instance details

Defined in Web.Internal.HttpApiData

HasResolution a => ToHttpApiData (Fixed a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData a => ToHttpApiData (First a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData a => ToHttpApiData (Last a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData a => ToHttpApiData (Dual a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData a => ToHttpApiData (Sum a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

ToHttpApiData a => ToHttpApiData (Product a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

(ToHttpApiData a, ToHttpApiData b) => ToHttpApiData (Either a b) Source #
>>> toUrlPiece (Left "err" :: Either String Int)
"left err"
>>> toUrlPiece (Right 3 :: Either String Int)
"right 3"
Instance details

Defined in Web.Internal.HttpApiData

class FromHttpApiData a where Source #

Parse value from HTTP API data.

WARNING: Do not derive this using DeriveAnyClass as the generated instance will loop indefinitely.

Minimal complete definition

parseUrlPiece | parseQueryParam

Methods

parseUrlPiece :: Text -> Either Text a Source #

Parse URL path piece.

parseHeader :: ByteString -> Either Text a Source #

Parse HTTP header value.

parseQueryParam :: Text -> Either Text a Source #

Parse query param value.

Instances
FromHttpApiData Bool Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Char Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Double Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Float Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Int Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Int8 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Int16 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Int32 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Int64 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Integer Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Natural Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Ordering Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Word Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Word8 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Word16 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Word32 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Word64 Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData () Source #
>>> parseUrlPiece "_" :: Either Text ()
Right ()
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Text Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Text Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData String Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Void Source #

Parsing a Void value is always an error, considering Void as a data type with no constructors.

Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Version Source #
>>> showVersion <$> parseUrlPiece "1.2.3"
Right "1.2.3"
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData All Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Any Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData UTCTime Source #
>>> parseUrlPiece "2015-10-03T00:14:24Z" :: Either Text UTCTime
Right 2015-10-03 00:14:24 UTC
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData SetCookie Source #

Note: this instance works correctly for alphanumeric name and value

>>> parseUrlPiece "SESSID=r2t5uvjq435r4q7ib3vtdjq120" :: Either Text SetCookie
Right (SetCookie {setCookieName = "SESSID", setCookieValue = "r2t5uvjq435r4q7ib3vtdjq120", setCookiePath = Nothing, setCookieExpires = Nothing, setCookieMaxAge = Nothing, setCookieDomain = Nothing, setCookieHttpOnly = False, setCookieSecure = False, setCookieSameSite = Nothing})
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData ZonedTime Source #
>>> 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
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData LocalTime Source #
>>> parseUrlPiece "2015-10-03T14:55:01" :: Either Text LocalTime
Right 2015-10-03 14:55:01
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData TimeOfDay Source #
>>> parseUrlPiece "14:55:01.333" :: Either Text TimeOfDay
Right 14:55:01.333
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData NominalDiffTime Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData Day Source #
>>> toGregorian <$> parseUrlPiece "2016-12-01"
Right (2016,12,1)
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData UUID Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (Maybe a) Source #
>>> parseUrlPiece "Just 123" :: Either Text (Maybe Int)
Right (Just 123)
Instance details

Defined in Web.Internal.HttpApiData

HasResolution a => FromHttpApiData (Fixed a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (First a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (Last a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (Dual a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (Sum a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (Product a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

(FromHttpApiData a, FromHttpApiData b) => FromHttpApiData (Either a b) Source #
>>> parseUrlPiece "Right 123" :: Either Text (Either String Int)
Right (Right 123)
Instance details

Defined in Web.Internal.HttpApiData

Maybe parsers

parseUrlPieceMaybe :: FromHttpApiData a => Text -> Maybe a Source #

Parse URL path piece in a Maybe.

>>> parseUrlPieceMaybe "12" :: Maybe Int
Just 12

parseHeaderMaybe :: FromHttpApiData a => ByteString -> Maybe a Source #

Parse HTTP header value in a Maybe.

>>> parseHeaderMaybe "hello" :: Maybe Text
Just "hello"

parseQueryParamMaybe :: FromHttpApiData a => Text -> Maybe a Source #

Parse query param value in a Maybe.

>>> parseQueryParamMaybe "true" :: Maybe Bool
Just True

Prefix parsers

parseUrlPieceWithPrefix :: FromHttpApiData a => Text -> Text -> Either Text a Source #

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)

parseHeaderWithPrefix :: FromHttpApiData a => ByteString -> ByteString -> Either Text a Source #

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==")

parseQueryParamWithPrefix :: FromHttpApiData a => Text -> Text -> Either Text a Source #

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

Multiple URL pieces

toUrlPieces :: (Functor t, ToHttpApiData a) => t a -> t Text Source #

Convert multiple values to a list of URL pieces.

>>> toUrlPieces [1, 2, 3] :: [Text]
["1","2","3"]

parseUrlPieces :: (Traversable t, FromHttpApiData a) => t Text -> Either Text (t a) Source #

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

Multiple query params

toQueryParams :: (Functor t, ToHttpApiData a) => t a -> t Text Source #

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

parseQueryParams :: (Traversable t, FromHttpApiData a) => t Text -> Either Text (t a) Source #

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

Parsers for Bounded Enums

parseBoundedUrlPiece :: (ToHttpApiData a, Bounded a, Enum a) => Text -> Either Text a Source #

Case insensitive.

Parse values case insensitively based on ToHttpApiData instance. Uses toUrlPiece to get possible values.

parseBoundedQueryParam :: (ToHttpApiData a, Bounded a, Enum a) => Text -> Either Text a Source #

Case insensitive.

Parse values case insensitively based on ToHttpApiData instance. Uses toQueryParam to get possible values.

parseBoundedHeader :: (ToHttpApiData a, Bounded a, Enum a) => ByteString -> Either Text a Source #

Parse values based on ToHttpApiData instance. Uses toHeader to get possible values.

parseBoundedEnumOf :: (Bounded a, Enum a) => (a -> Text) -> Text -> Either Text a Source #

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.

parseBoundedEnumOfI :: (Bounded a, Enum a) => (a -> Text) -> Text -> Either Text a Source #

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.

parseBoundedTextData :: (Show a, Bounded a, Enum a) => Text -> Either Text a Source #

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

Lenient data

newtype LenientData a Source #

Lenient parameters. FromHttpApiData combinators always return Right.

Since: http-api-data-0.3.5

Constructors

LenientData 
Instances
Functor LenientData Source # 
Instance details

Defined in Web.Internal.HttpApiData

Methods

fmap :: (a -> b) -> LenientData a -> LenientData b #

(<$) :: a -> LenientData b -> LenientData a #

Foldable LenientData Source # 
Instance details

Defined in Web.Internal.HttpApiData

Methods

fold :: Monoid m => LenientData m -> m #

foldMap :: Monoid m => (a -> m) -> LenientData a -> m #

foldr :: (a -> b -> b) -> b -> LenientData a -> b #

foldr' :: (a -> b -> b) -> b -> LenientData a -> b #

foldl :: (b -> a -> b) -> b -> LenientData a -> b #

foldl' :: (b -> a -> b) -> b -> LenientData a -> b #

foldr1 :: (a -> a -> a) -> LenientData a -> a #

foldl1 :: (a -> a -> a) -> LenientData a -> a #

toList :: LenientData a -> [a] #

null :: LenientData a -> Bool #

length :: LenientData a -> Int #

elem :: Eq a => a -> LenientData a -> Bool #

maximum :: Ord a => LenientData a -> a #

minimum :: Ord a => LenientData a -> a #

sum :: Num a => LenientData a -> a #

product :: Num a => LenientData a -> a #

Traversable LenientData Source # 
Instance details

Defined in Web.Internal.HttpApiData

Methods

traverse :: Applicative f => (a -> f b) -> LenientData a -> f (LenientData b) #

sequenceA :: Applicative f => LenientData (f a) -> f (LenientData a) #

mapM :: Monad m => (a -> m b) -> LenientData a -> m (LenientData b) #

sequence :: Monad m => LenientData (m a) -> m (LenientData a) #

Eq a => Eq (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

Data a => Data (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

Methods

gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> LenientData a -> c (LenientData a) #

gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (LenientData a) #

toConstr :: LenientData a -> Constr #

dataTypeOf :: LenientData a -> DataType #

dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (LenientData a)) #

dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (LenientData a)) #

gmapT :: (forall b. Data b => b -> b) -> LenientData a -> LenientData a #

gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> LenientData a -> r #

gmapQr :: (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> LenientData a -> r #

gmapQ :: (forall d. Data d => d -> u) -> LenientData a -> [u] #

gmapQi :: Int -> (forall d. Data d => d -> u) -> LenientData a -> u #

gmapM :: Monad m => (forall d. Data d => d -> m d) -> LenientData a -> m (LenientData a) #

gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> LenientData a -> m (LenientData a) #

gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> LenientData a -> m (LenientData a) #

Ord a => Ord (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

Read a => Read (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

Show a => Show (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

FromHttpApiData a => FromHttpApiData (LenientData a) Source # 
Instance details

Defined in Web.Internal.HttpApiData

Other helpers

showTextData :: Show a => a -> Text Source #

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"

readTextData :: Read a => Text -> Either Text a Source #

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.