@@ -195,6 +195,7 @@ import Data.Typeable (Typeable)
195import GHC.Generics
195import GHC.Generics
196import GHC.TypeLits
196import GHC.TypeLits
197import System.IO.Unsafe (unsafePerformIO)
197import System.IO.Unsafe (unsafePerformIO)
198+import Web.HttpApiData (ToHttpApiData (..))
198import qualified Blaze.ByteString.Builder as BB
199import qualified Blaze.ByteString.Builder as BB
199import qualified Data.Aeson as A
200import qualified Data.Aeson as A
200import qualified Data.Binary.Builder as R
201import qualified Data.Binary.Builder as R
@@ -501,6 +502,9 @@ instance HttpMethod method => RequestComponent (Womb "method" method) where
501-- > https "httpbin.org" /: "foo" /: "bar/baz"
502-- > https "httpbin.org" /: "foo" /: "bar/baz"
502-- > -- https://httpbin.org/foo/bar%2Fbaz
503-- > -- https://httpbin.org/foo/bar%2Fbaz
505+-- > https "httpbin.org" /: "bytes" /: (10 :: Int)
506+-- > -- https://httpbin.org/bytes/10
504-- > https "юникод.рф"
508-- > https "юникод.рф"
505-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
509-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
@@ -520,11 +524,12 @@ http = Url Http . pure
520https :: Text -> Url 'Https
524https :: Text -> Url 'Https
521https = Url Https . pure
525https = Url Https . pure
523−-- | Grow given 'Url' appending a single path segment to it.
527+-- | Grow given 'Url' appending a single path segment to it. Note that the
528+-- path segment can be of any type that is an instance of 'ToHttpApiData'.
525infixl 5 /:
530infixl 5 /:
526−(/:) :: Url scheme -> Text -> Url scheme
531+(/:) :: ToHttpApiData a => Url scheme -> a -> Url scheme
527−Url secure path /: segment = Url secure (NE.cons segment path)
532+Url secure path /: segment = Url secure (NE.cons (toUrlPiece segment) path)
529-- | The 'parseUrlHttp' function provides an alternative method to get 'Url'
534-- | The 'parseUrlHttp' function provides an alternative method to get 'Url'
530-- (possibly with some 'Option's) from a 'ByteString'. This is useful when
535-- (possibly with some 'Option's) from a 'ByteString'. This is useful when
@@ -670,7 +675,8 @@ newtype FormUrlEncodedParam = FormUrlEncodedParam [(Text, Maybe Text)]
670 deriving (Semigroup, Monoid)
675 deriving (Semigroup, Monoid)
672instance QueryParam FormUrlEncodedParam where
677instance QueryParam FormUrlEncodedParam where
678+ queryParam name mvalue =
673− queryParam name mvalue = FormUrlEncodedParam [(name, mvalue)]
679+ FormUrlEncodedParam [(name, toQueryParam <$> mvalue)]
675-- | A type class for things that can be interpreted as HTTP
681-- | A type class for things that can be interpreted as HTTP
676-- 'L.RequestBody'.
682-- 'L.RequestBody'.
@@ -771,7 +777,7 @@ instance RequestComponent (Option scheme) where
771-- $query-parameters
777-- $query-parameters
773-- This section describes a polymorphic interface that can be used to
779-- This section describes a polymorphic interface that can be used to
774−-- construct query parameters (of type 'Option') and form url encoded bodies
780+-- construct query parameters (of type 'Option') and form URL-encoded bodies
775-- (of type 'FormUrlEncodedParam').
781-- (of type 'FormUrlEncodedParam').
777-- | This operator builds a query parameter that will be included in URL of
783-- | This operator builds a query parameter that will be included in URL of
@@ -783,7 +789,7 @@ instance RequestComponent (Option scheme) where
783-- > name =: value = queryParam name (pure value)
789-- > name =: value = queryParam name (pure value)
785infix 7 =:
791infix 7 =:
786−(=:) :: QueryParam a => Text -> Text -> a
792+(=:) :: (QueryParam param, ToHttpApiData a) => Text -> a -> param
787name =: value = queryParam name (pure value)
793name =: value = queryParam name (pure value)
789-- | Construct a flag, that is, valueless query parameter. For example, in
795-- | Construct a flag, that is, valueless query parameter. For example, in
@@ -795,25 +801,26 @@ name =: value = queryParam name (pure value)
796-- > queryFlag name = queryParam name Nothing
802-- > queryFlag name = queryParam name Nothing
798−queryFlag :: QueryParam a => Text -> a
804+queryFlag :: QueryParam param => Text -> param
799−queryFlag name = queryParam name Nothing
805+queryFlag name = queryParam name (Nothing :: Maybe ())
801-- | A type class for query-parameter-like things. The reason to have
807-- | A type class for query-parameter-like things. The reason to have
802-- overloaded 'queryParam' is to be able to use it as an 'Option' and as a
808-- overloaded 'queryParam' is to be able to use it as an 'Option' and as a
803-- 'FormUrlEncodedParam' when constructing form URL encoded request bodies.
809-- 'FormUrlEncodedParam' when constructing form URL encoded request bodies.
804-- Having the same syntax for these cases seems natural and user-friendly.
810-- Having the same syntax for these cases seems natural and user-friendly.
806−class QueryParam a where
812+class QueryParam param where
808 -- | Create a query parameter with given name and value. If value is
814 -- | Create a query parameter with given name and value. If value is
809 -- 'Nothing', it won't be included at all (i.e. you create a flag this
815 -- 'Nothing', it won't be included at all (i.e. you create a flag this
810 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
816 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
811 -- method, because they are easier to read.
817 -- method, because they are easier to read.
813− queryParam :: Text -> Maybe Text -> a
819+ queryParam :: ToHttpApiData a => Text -> Maybe a -> param
815instance QueryParam (Option scheme) where
821instance QueryParam (Option scheme) where
816− queryParam name mvalue = withQueryParams ((:) (name, mvalue))
822+ queryParam name mvalue =
823+ withQueryParams ((:) (name, toQueryParam <$> mvalue))
818----------------------------------------------------------------------------
825----------------------------------------------------------------------------
819-- Request — Optional parameters — Headers
826-- Request — Optional parameters — Headers