    {-# LANGUAGE FlexibleInstances, OverloadedStrings #-}
    {-# OPTIONS_GHC -fno-warn-orphans #-}

    -- |
    -- Module      : Network.Wreq.Types
    -- Copyright   : (c) 2014 Bryan O'Sullivan
    --
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- HTTP client types.

    module Network.Wreq.Types
        (
        -- * Client configuration
          Options(..)
        , Auth(..)
        , AWSAuthVersion(..)
        , ResponseChecker
        -- * Request payloads
        , Payload(..)
        , Postable(..)
        , Patchable(..)
        , Putable(..)
        -- ** URL-encoded forms
        , FormParam(..)
        , FormValue(..)
        -- * Headers
        , ContentType
        , Link(..)
        -- * Errors
        , JSONError(..)
        -- * Request handling
        , Req
        , reqURL
        , Run
        ) where

    import Control.Lens ((&), (.~))
    import Data.Aeson (Encoding, Value, encode)
    import Data.Aeson.Encoding (encodingToLazyByteString)
    import Data.Int (Int8, Int16, Int32, Int64)
    import Data.Word (Word, Word8, Word16, Word32, Word64)
    import Network.HTTP.Client (Request(method))
    import Network.HTTP.Client.MultipartFormData (Part, formDataBody)
    import Network.Wreq.Internal.Types
    import qualified Data.ByteString as S
    import qualified Data.ByteString.Lazy as L
    import qualified Data.Text as T
    import qualified Data.Text.Encoding as T
    import qualified Data.Text.Lazy as TL
    import qualified Data.Text.Lazy.Builder as TL
    import qualified Network.HTTP.Client as HTTP
    import qualified Network.Wreq.Internal.Lens as Lens

    -- By default if the type is Putable, we use that as postPayload
    instance Postable Part
    instance Postable [Part]
    instance Postable [(S.ByteString, S.ByteString)]
    instance Postable (S.ByteString, S.ByteString)
    instance Postable [FormParam]
    instance Postable FormParam
    instance Postable Payload
    instance Postable S.ByteString
    instance Postable L.ByteString
    instance Postable Value
    instance Postable Encoding

    -- By default if the type is Putable, we use that as patchPayload
    instance Patchable Part
    instance Patchable [Part]
    instance Patchable [(S.ByteString, S.ByteString)]
    instance Patchable (S.ByteString, S.ByteString)
    instance Patchable [FormParam]
    instance Patchable FormParam
    instance Patchable Payload
    instance Patchable S.ByteString
    instance Patchable L.ByteString
    instance Patchable Value
    instance Patchable Encoding

    instance Putable Part where
        putPayload :: Part -> Request -> IO Request
    putPayload Part
    a = [Part] -> Request -> IO Request
    forall a. Putable a => a -> Request -> IO Request
    putPayload [Part
    a]

    instance Putable [Part] where
        putPayload :: [Part] -> Request -> IO Request
    putPayload [Part]
    p Request
    req =
            -- According to doc, formDataBody changes the request type to POST which is wrong; change it back
            (\Request
    r -> Request
    r{method=method req}) (Request -> Request) -> IO Request -> IO Request
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` [Part] -> Request -> IO Request
    forall (m :: * -> *). MonadIO m => [Part] -> Request -> m Request
    formDataBody [Part]
    p Request
    req

    instance Putable [(S.ByteString, S.ByteString)] where
        putPayload :: [(ByteString, ByteString)] -> Request -> IO Request
    putPayload [(ByteString, ByteString)]
    ps Request
    req =
            -- According to doc, urlEncodedBody changes the request type to POST which is wrong; change it back
            Request -> IO Request
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Request -> IO Request) -> Request -> IO Request
    forall a b. (a -> b) -> a -> b
    $ [(ByteString, ByteString)] -> Request -> Request
    HTTP.urlEncodedBody [(ByteString, ByteString)]
    ps Request
    req {method=method req}

    instance Putable (S.ByteString, S.ByteString) where
        putPayload :: (ByteString, ByteString) -> Request -> IO Request
    putPayload (ByteString, ByteString)
    p = [(ByteString, ByteString)] -> Request -> IO Request
    forall a. Putable a => a -> Request -> IO Request
    putPayload [(ByteString, ByteString)
    p]

    instance Putable [FormParam] where
        putPayload :: [FormParam] -> Request -> IO Request
    putPayload [FormParam]
    ps = [(ByteString, ByteString)] -> Request -> IO Request
    forall a. Putable a => a -> Request -> IO Request
    putPayload ((FormParam -> (ByteString, ByteString))
    -> [FormParam] -> [(ByteString, ByteString)]
    forall a b. (a -> b) -> [a] -> [b]
    map FormParam -> (ByteString, ByteString)
    f [FormParam]
    ps)
          where f :: FormParam -> (ByteString, ByteString)
    f (ByteString
    a := v
    b) = (ByteString
    a, v -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue v
    b)

    instance Putable FormParam where
        putPayload :: FormParam -> Request -> IO Request
    putPayload FormParam
    p = [FormParam] -> Request -> IO Request
    forall a. Putable a => a -> Request -> IO Request
    putPayload [FormParam
    p]

    instance Putable Payload where
        putPayload :: Payload -> Request -> IO Request
    putPayload Payload
    pl =
          case Payload
    pl of
            Raw ByteString
    ct RequestBody
    rb -> ByteString -> RequestBody -> Request -> IO Request
    payload ByteString
    ct RequestBody
    rb

    instance Putable S.ByteString where
        putPayload :: ByteString -> Request -> IO Request
    putPayload = ByteString -> RequestBody -> Request -> IO Request
    payload ByteString
    "application/octet-stream" (RequestBody -> Request -> IO Request)
    -> (ByteString -> RequestBody)
    -> ByteString
    -> Request
    -> IO Request
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> RequestBody
    HTTP.RequestBodyBS

    instance Putable L.ByteString where
        putPayload :: ByteString -> Request -> IO Request
    putPayload = ByteString -> RequestBody -> Request -> IO Request
    payload ByteString
    "application/octet-stream" (RequestBody -> Request -> IO Request)
    -> (ByteString -> RequestBody)
    -> ByteString
    -> Request
    -> IO Request
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> RequestBody
    HTTP.RequestBodyLBS

    instance Putable Value where
        putPayload :: Value -> Request -> IO Request
    putPayload = ByteString -> RequestBody -> Request -> IO Request
    payload ByteString
    "application/json" (RequestBody -> Request -> IO Request)
    -> (Value -> RequestBody) -> Value -> Request -> IO Request
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> RequestBody
    HTTP.RequestBodyLBS (ByteString -> RequestBody)
    -> (Value -> ByteString) -> Value -> RequestBody
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Value -> ByteString
    forall a. ToJSON a => a -> ByteString
    encode

    instance Putable Encoding where
        putPayload :: Encoding -> Request -> IO Request
    putPayload = ByteString -> RequestBody -> Request -> IO Request
    payload ByteString
    "application/json" (RequestBody -> Request -> IO Request)
    -> (Encoding -> RequestBody) -> Encoding -> Request -> IO Request
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> RequestBody
    HTTP.RequestBodyLBS (ByteString -> RequestBody)
    -> (Encoding -> ByteString) -> Encoding -> RequestBody
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
          Encoding -> ByteString
    forall a. Encoding' a -> ByteString
    encodingToLazyByteString

    instance FormValue T.Text where
        renderFormValue :: Text -> ByteString
    renderFormValue = Text -> ByteString
    T.encodeUtf8

    instance FormValue TL.Text where
        renderFormValue :: Text -> ByteString
    renderFormValue = Text -> ByteString
    T.encodeUtf8 (Text -> ByteString) -> (Text -> Text) -> Text -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    TL.toStrict

    instance FormValue TL.Builder where
        renderFormValue :: Builder -> ByteString
    renderFormValue = Text -> ByteString
    T.encodeUtf8 (Text -> ByteString) -> (Builder -> Text) -> Builder -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    TL.toStrict (Text -> Text) -> (Builder -> Text) -> Builder -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Builder -> Text
    TL.toLazyText

    instance FormValue String where
        renderFormValue :: String -> ByteString
    renderFormValue = Text -> ByteString
    T.encodeUtf8 (Text -> ByteString) -> (String -> Text) -> String -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> Text
    T.pack

    instance FormValue S.ByteString where
        renderFormValue :: ByteString -> ByteString
    renderFormValue = ByteString -> ByteString
    forall a. a -> a
    id

    instance FormValue L.ByteString where
        renderFormValue :: ByteString -> ByteString
    renderFormValue = [ByteString] -> ByteString
    S.concat ([ByteString] -> ByteString)
    -> (ByteString -> [ByteString]) -> ByteString -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> [ByteString]
    L.toChunks

    instance FormValue Int where renderFormValue :: Int -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Int -> String) -> Int -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> String
    forall a. Show a => a -> String
    show
    instance FormValue Int8 where renderFormValue :: Int8 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Int8 -> String) -> Int8 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int8 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Int16 where renderFormValue :: Int16 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Int16 -> String) -> Int16 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int16 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Int32 where renderFormValue :: Int32 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Int32 -> String) -> Int32 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int32 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Int64 where renderFormValue :: Int64 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Int64 -> String) -> Int64 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int64 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Integer where renderFormValue :: Integer -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString)
    -> (Integer -> String) -> Integer -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Integer -> String
    forall a. Show a => a -> String
    show

    instance FormValue Word where renderFormValue :: Word -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Word -> String) -> Word -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word -> String
    forall a. Show a => a -> String
    show
    instance FormValue Word8 where renderFormValue :: Word8 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Word8 -> String) -> Word8 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word8 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Word16 where renderFormValue :: Word16 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString)
    -> (Word16 -> String) -> Word16 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word16 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Word32 where renderFormValue :: Word32 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString)
    -> (Word32 -> String) -> Word32 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word32 -> String
    forall a. Show a => a -> String
    show
    instance FormValue Word64 where renderFormValue :: Word64 -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString)
    -> (Word64 -> String) -> Word64 -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Word64 -> String
    forall a. Show a => a -> String
    show

    instance FormValue Float where renderFormValue :: Float -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString) -> (Float -> String) -> Float -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Float -> String
    forall a. Show a => a -> String
    show
    instance FormValue Double where renderFormValue :: Double -> ByteString
    renderFormValue = String -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue (String -> ByteString)
    -> (Double -> String) -> Double -> ByteString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Double -> String
    forall a. Show a => a -> String
    show

    instance FormValue () where renderFormValue :: () -> ByteString
    renderFormValue ()
    _ = ByteString
    ""

    instance (FormValue a) => FormValue (Maybe a) where
        renderFormValue :: Maybe a -> ByteString
    renderFormValue (Just a
    a) = a -> ByteString
    forall a. FormValue a => a -> ByteString
    renderFormValue a
    a
        renderFormValue Maybe a
    Nothing  = ByteString
    ""

    payload :: S.ByteString -> HTTP.RequestBody -> Request -> IO Request
    payload :: ByteString -> RequestBody -> Request -> IO Request
    payload ByteString
    ct RequestBody
    body Request
    req =
      Request -> IO Request
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Request -> IO Request) -> Request -> IO Request
    forall a b. (a -> b) -> a -> b
    $ Request
    req Request -> (Request -> Request) -> Request
    forall a b. a -> (a -> b) -> b
    & HeaderName -> ByteString -> Request -> Request
    Lens.maybeSetHeader HeaderName
    "Content-Type" ByteString
    ct
                   Request -> (Request -> Request) -> Request
    forall a b. a -> (a -> b) -> b
    & (RequestBody -> Identity RequestBody)
    -> Request -> Identity Request
    Lens' Request RequestBody
    Lens.requestBody ((RequestBody -> Identity RequestBody)
     -> Request -> Identity Request)
    -> RequestBody -> Request -> Request
    forall s t a b. ASetter s t a b -> b -> s -> t
    .~ RequestBody
    body