    {-# LANGUAGE FlexibleContexts, OverloadedStrings #-}

    -- |
    -- Module      : Network.Wreq
    -- Copyright   : (c) 2014 Bryan O'Sullivan
    --
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- A library for client-side HTTP requests, focused on ease of use.
    --
    -- When reading the examples in this module, you should assume the
    -- following environment:
    --
    -- @
    -- \-\- Make it easy to write literal 'S.ByteString' and 'Text' values.
    -- \{\-\# LANGUAGE OverloadedStrings \#\-\}
    --
    -- \-\- Our handy module.
    -- import "Network.Wreq"
    --
    -- \-\- Operators such as ('&') and ('.~').
    -- import "Control.Lens"
    --
    -- \-\- Conversion of Haskell values to JSON.
    -- import "Data.Aeson" ('Data.Aeson.toJSON')
    --
    -- \-\- Easy traversal of JSON data.
    -- import "Data.Aeson.Lens" ('Data.Aeson.Lens.key', 'Data.Aeson.Lens.nth')
    -- @
    --
    -- There exist some less frequently used lenses that are not exported
    -- from this module; these can be found in "Network.Wreq.Lens".

    module Network.Wreq
        (
        -- * HTTP verbs

        -- ** Sessions
        -- $session

        -- ** GET
          get
        , getWith
        -- ** POST
        -- $postable
        , post
        , postWith
        -- ** HEAD
        , head_
        , headWith
        -- ** OPTIONS
        , options
        , optionsWith
        -- ** PUT
        , put
        , putWith
        -- ** DELETE
        , delete
        , deleteWith
        -- ** Custom Method
        , customMethod
        , customMethodWith
        , customHistoriedMethod
        , customHistoriedMethodWith
        -- ** Custom Payload Method
        , customPayloadMethod
        , customPayloadMethodWith
        , customHistoriedPayloadMethod
        , customHistoriedPayloadMethodWith
        -- * Incremental consumption of responses
        -- ** GET
        , foldGet
        , foldGetWith

        -- * Configuration
        , Options
        , defaults
        , Lens.manager
        , Lens.header
        , Lens.param
        , Lens.redirects
        , Lens.headers
        , Lens.params
        , Lens.cookie
        , Lens.cookies
        , Lens.checkResponse

        -- ** Authentication
        -- $auth
        , Auth
        , AWSAuthVersion(..)
        , Lens.auth
        , basicAuth
        , oauth1Auth
        , oauth2Bearer
        , oauth2Token
        , awsAuth
        , awsFullAuth
        , awsSessionTokenAuth
        -- ** Proxy settings
        , Proxy(Proxy)
        , Lens.proxy
        , httpProxy
        -- ** Using a manager with defaults
        , withManager

        -- * Payloads for POST and PUT
        , Payload(..)
        -- ** URL-encoded form data
        , FormParam(..)
        , FormValue
        -- ** Multipart form data
        , Form.Part
        , Lens.partName
        , Lens.partFileName
        , Lens.partContentType
        , Lens.partGetBody
        -- *** Smart constructors
        , Form.partBS
        , Form.partLBS
        , partText
        , partString
        , Form.partFile
        , Form.partFileSource

        -- * Responses
        , Response
        , Lens.responseBody
        , Lens.responseHeader
        , Lens.responseLink
        , Lens.responseCookie
        , Lens.responseHeaders
        , Lens.responseCookieJar
        , Lens.responseStatus
        , Lens.Status
        , Lens.statusCode
        , Lens.statusMessage
        , HistoriedResponse
        , Lens.hrFinalRequest
        , Lens.hrFinalResponse
        , Lens.hrRedirects
        -- ** Link headers
        , Lens.Link
        , Lens.linkURL
        , Lens.linkParams
        -- ** Decoding responses
        , JSONError(..)
        , asJSON
        , asValue

        -- * Cookies
        -- $cookielenses
        , Lens.Cookie
        , Lens.cookieName
        , Lens.cookieValue
        , Lens.cookieExpiryTime
        , Lens.cookieDomain
        , Lens.cookiePath

        -- * Parsing responses
        , Lens.atto
        , Lens.atto_
        ) where

    import Control.Lens ((.~), (&))
    import Control.Monad (unless)
    import Control.Monad.Catch (MonadThrow(throwM))
    import Data.Aeson (FromJSON)
    import Data.Maybe (fromMaybe)
    import Data.Text (Text)
    import Data.Text.Encoding (encodeUtf8)
    import Network.HTTP.Client (HistoriedResponse)
    import Network.HTTP.Client.Internal (Proxy(..), Response)
    import Network.Wreq.Internal
    import Network.Wreq.Types (Options)
    import Network.Wreq.Types hiding (Options(..))
    import Prelude hiding (head)
    import qualified Data.Aeson as Aeson
    import qualified Data.ByteString as S
    import qualified Data.ByteString.Lazy as L
    import qualified Data.Text as T
    import qualified Network.HTTP.Client as HTTP
    import qualified Network.HTTP.Client.MultipartFormData as Form
    import qualified Network.Wreq.Lens as Lens
    import qualified Network.Wreq.Types as Wreq
    import qualified Data.ByteString.Char8 as BC8

    -- | Issue a GET request.
    --
    -- Example:
    --
    -- @
    --'get' \"http:\/\/httpbin.org\/get\"
    -- @
    --
    -- >>> r <- get "http://httpbin.org/get"
    -- >>> r ^. responseStatus . statusCode
    -- 200
    get :: String -> IO (Response L.ByteString)
    get :: String -> IO (Response ByteString)
    get url :: String
    url = Options -> String -> IO (Response ByteString)
    getWith Options
    defaults String
    url

    withManager :: (Options -> IO a) -> IO a
    withManager :: (Options -> IO a) -> IO a
    withManager act :: Options -> IO a
    act = do
      Manager
    mgr <- ManagerSettings -> IO Manager
    HTTP.newManager ManagerSettings
    defaultManagerSettings
      Options -> IO a
    act Options
    defaults { manager :: Mgr
    Wreq.manager = Manager -> Mgr
    forall a b. b -> Either a b
    Right Manager
    mgr }

    -- | Issue a GET request, using the supplied 'Options'.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.param' \"foo\" '.~' [\"bar\"]
    --'getWith' opts \"http:\/\/httpbin.org\/get\"
    -- @
    --
    -- >>> let opts = defaults & param "foo" .~ ["bar"]
    -- >>> r <- getWith opts "http://httpbin.org/get"
    -- >>> r ^? responseBody . key "url"
    -- Just (String "http://httpbin.org/get?foo=bar")
    getWith :: Options -> String -> IO (Response L.ByteString)
    getWith :: Options -> String -> IO (Response ByteString)
    getWith opts :: Options
    opts url :: String
    url = Run ByteString
    runRead Run ByteString -> IO Req -> IO (Response ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Options -> String -> IO Req
    prepareGet Options
    opts String
    url

    -- | Issue a POST request.
    --
    -- Example:
    --
    -- @
    --'post' \"http:\/\/httpbin.org\/post\" ('Aeson.toJSON' [1,2,3])
    -- @
    --
    -- >>> r <- post "http://httpbin.org/post" (toJSON [1,2,3])
    -- >>> r ^? responseBody . key "json" . nth 2
    -- Just (Number 3.0)
    post :: Postable a => String -> a -> IO (Response L.ByteString)
    post :: String -> a -> IO (Response ByteString)
    post url :: String
    url payload :: a
    payload = Options -> String -> a -> IO (Response ByteString)
    forall a.
    Postable a =>
    Options -> String -> a -> IO (Response ByteString)
    postWith Options
    defaults String
    url a
    payload

    -- | Issue a POST request, using the supplied 'Options'.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.param' \"foo\" '.~' [\"bar\"]
    --'postWith' opts \"http:\/\/httpbin.org\/post\" ('Aeson.toJSON' [1,2,3])
    -- @
    --
    -- >>> let opts = defaults & param "foo" .~ ["bar"]
    -- >>> r <- postWith opts "http://httpbin.org/post" (toJSON [1,2,3])
    -- >>> r ^? responseBody . key "url"
    -- Just (String "http://httpbin.org/post?foo=bar")
    postWith :: Postable a => Options -> String -> a -> IO (Response L.ByteString)
    postWith :: Options -> String -> a -> IO (Response ByteString)
    postWith opts :: Options
    opts url :: String
    url payload :: a
    payload = Run ByteString
    runRead Run ByteString -> IO Req -> IO (Response ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Options -> String -> a -> IO Req
    forall a. Postable a => Options -> String -> a -> IO Req
    preparePost Options
    opts String
    url a
    payload

    -- | Issue a HEAD request.
    --
    -- Example:
    --
    -- @
    --'head_' \"http:\/\/httpbin.org\/get\"
    -- @
    --
    -- >>> r <- head_ "http://httpbin.org/get"
    -- >>> r ^? responseHeader "Content-Type"
    -- Just "application/json"
    head_ :: String -> IO (Response ())
    head_ :: String -> IO (Response ())
    head_ = Options -> String -> IO (Response ())
    headWith (Options
    defaults Options -> (Options -> Options) -> Options
    forall a b. a -> (a -> b) -> b
    & (Int -> Identity Int) -> Options -> Identity Options
    Lens' Options Int
    Lens.redirects ((Int -> Identity Int) -> Options -> Identity Options)
    -> Int -> Options -> Options
    forall s t a b. ASetter s t a b -> b -> s -> t
    .~ 0)

    -- | Issue a HEAD request, using the supplied 'Options'.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.param' \"foo\" '.~' [\"bar\"]
    --'headWith' opts \"http:\/\/httpbin.org\/get\"
    -- @
    --
    -- >>> let opts = defaults & param "foo" .~ ["bar"]
    -- >>> r <- headWith opts "http://httpbin.org/get"
    -- >>> r ^? responseHeader "Connection"
    -- Just "keep-alive"
    headWith :: Options -> String -> IO (Response ())
    headWith :: Options -> String -> IO (Response ())
    headWith opts :: Options
    opts url :: String
    url = Run ()
    runIgnore Run () -> IO Req -> IO (Response ())
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Options -> String -> IO Req
    prepareHead Options
    opts String
    url

    -- | Issue a PUT request.
    put :: Putable a => String -> a -> IO (Response L.ByteString)
    put :: String -> a -> IO (Response ByteString)
    put url :: String
    url payload :: a
    payload = Options -> String -> a -> IO (Response ByteString)
    forall a.
    Putable a =>
    Options -> String -> a -> IO (Response ByteString)
    putWith Options
    defaults String
    url a
    payload

    -- | Issue a PUT request, using the supplied 'Options'.
    putWith :: Putable a => Options -> String -> a -> IO (Response L.ByteString)
    putWith :: Options -> String -> a -> IO (Response ByteString)
    putWith opts :: Options
    opts url :: String
    url payload :: a
    payload = Run ByteString
    runRead Run ByteString -> IO Req -> IO (Response ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Options -> String -> a -> IO Req
    forall a. Putable a => Options -> String -> a -> IO Req
    preparePut Options
    opts String
    url a
    payload

    -- | Issue an OPTIONS request.
    --
    -- Example:
    --
    -- @
    --'options' \"http:\/\/httpbin.org\/get\"
    -- @
    --
    -- See 'Lens.atto' for a more complex worked example.
    options :: String -> IO (Response ())
    options :: String -> IO (Response ())
    options = Options -> String -> IO (Response ())
    optionsWith Options
    defaults

    -- | Issue an OPTIONS request, using the supplied 'Options'.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.param' \"foo\" '.~' [\"bar\"]
    --'optionsWith' opts \"http:\/\/httpbin.org\/get\"
    -- @
    optionsWith :: Options -> String -> IO (Response ())
    optionsWith :: Options -> String -> IO (Response ())
    optionsWith opts :: Options
    opts url :: String
    url = Run ()
    runIgnore Run () -> IO Req -> IO (Response ())
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Options -> String -> IO Req
    prepareOptions Options
    opts String
    url

    -- | Issue a DELETE request.
    --
    -- Example:
    --
    -- @
    --'delete' \"http:\/\/httpbin.org\/delete\"
    -- @
    --
    -- >>> r <- delete "http://httpbin.org/delete"
    -- >>> r ^. responseStatus . statusCode
    -- 200
    delete :: String -> IO (Response L.ByteString)
    delete :: String -> IO (Response ByteString)
    delete = Options -> String -> IO (Response ByteString)
    deleteWith Options
    defaults

    -- | Issue a DELETE request, using the supplied 'Options'.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.redirects' '.~' 0
    --'deleteWith' opts \"http:\/\/httpbin.org\/delete\"
    -- @
    --
    -- >>> let opts = defaults & redirects .~ 0
    -- >>> r <- deleteWith opts "http://httpbin.org/delete"
    -- >>> r ^. responseStatus . statusCode
    -- 200
    deleteWith :: Options -> String -> IO (Response L.ByteString)
    deleteWith :: Options -> String -> IO (Response ByteString)
    deleteWith opts :: Options
    opts url :: String
    url = Run ByteString
    runRead Run ByteString -> IO Req -> IO (Response ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Options -> String -> IO Req
    prepareDelete Options
    opts String
    url

    -- | Issue a custom-method request
    --
    -- Example:
    --
    -- @
    -- 'customMethod' \"PATCH\" \"http:\/\/httpbin.org\/patch\"
    -- @
    --
    -- >>> r <- customMethod "PATCH" "http://httpbin.org/patch"
    -- >>> r ^. responseStatus . statusCode
    -- 200
    customMethod :: String -> String -> IO (Response L.ByteString)
    customMethod :: String -> String -> IO (Response ByteString)
    customMethod method :: String
    method url :: String
    url = String -> Options -> String -> IO (Response ByteString)
    customMethodWith String
    method Options
    defaults String
    url

    -- | Issue a custom request method request, using the supplied 'Options'.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.redirects' '.~' 0
    --'customMethodWith' \"PATCH\" opts \"http:\/\/httpbin.org\/patch\"
    -- @
    --
    -- >>> let opts = defaults & redirects .~ 0
    -- >>> r <- customMethodWith "PATCH" opts "http://httpbin.org/patch"
    -- >>> r ^. responseStatus . statusCode
    -- 200
    customMethodWith :: String -> Options -> String -> IO (Response L.ByteString)
    customMethodWith :: String -> Options -> String -> IO (Response ByteString)
    customMethodWith method :: String
    method opts :: Options
    opts url :: String
    url = Run ByteString
    runRead Run ByteString -> IO Req -> IO (Response ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Method -> Options -> String -> IO Req
    prepareMethod Method
    methodBS Options
    opts String
    url
      where
        methodBS :: Method
    methodBS = String -> Method
    BC8.pack String
    method

    -- | Issue a custom request method. Keep track of redirects and return the 'HistoriedResponse'
    --
    -- Example:
    --
    -- @
    -- 'customHistoriedMethod' \"GET\" \"http:\/\/httpbin.org\/redirect\/3\"
    -- @
    --
    -- >>> r <- customHistoriedMethod "GET" "http://httpbin.org/redirect/3"
    -- >>> length (r ^. hrRedirects)
    -- 3
    --
    -- @since 0.5.2.0
    customHistoriedMethod :: String -> String -> IO (HistoriedResponse L.ByteString)
    customHistoriedMethod :: String -> String -> IO (HistoriedResponse ByteString)
    customHistoriedMethod method :: String
    method url :: String
    url = String -> Options -> String -> IO (HistoriedResponse ByteString)
    customHistoriedMethodWith String
    method Options
    defaults String
    url

    -- | Issue a custom request method request, using the supplied 'Options'.
    -- Keep track of redirects and return the 'HistoriedResponse'.
    --
    -- @since 0.5.2.0
    customHistoriedMethodWith :: String -> Options -> String -> IO (HistoriedResponse L.ByteString)
    customHistoriedMethodWith :: String -> Options -> String -> IO (HistoriedResponse ByteString)
    customHistoriedMethodWith method :: String
    method opts :: Options
    opts url :: String
    url =
        RunHistory ByteString
    runReadHistory RunHistory ByteString
    -> IO Req -> IO (HistoriedResponse ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Method -> Options -> String -> IO Req
    prepareMethod Method
    methodBS Options
    opts String
    url
      where
        methodBS :: Method
    methodBS = String -> Method
    BC8.pack String
    method

    -- | Issue a custom-method request with a payload
    customPayloadMethod :: Postable a => String -> String -> a
                        -> IO (Response L.ByteString)

    customPayloadMethod :: String -> String -> a -> IO (Response ByteString)
    customPayloadMethod method :: String
    method url :: String
    url payload :: a
    payload =
      String -> Options -> String -> a -> IO (Response ByteString)
    forall a.
    Postable a =>
    String -> Options -> String -> a -> IO (Response ByteString)
    customPayloadMethodWith String
    method Options
    defaults String
    url a
    payload

    -- | Issue a custom-method request with a payload, using the supplied 'Options'.
    customPayloadMethodWith :: Postable a => String -> Options -> String -> a
                            -> IO (Response L.ByteString)

    customPayloadMethodWith :: String -> Options -> String -> a -> IO (Response ByteString)
    customPayloadMethodWith method :: String
    method opts :: Options
    opts url :: String
    url payload :: a
    payload =
      Run ByteString
    runRead Run ByteString -> IO Req -> IO (Response ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Method -> Options -> String -> a -> IO Req
    forall a. Postable a => Method -> Options -> String -> a -> IO Req
    preparePayloadMethod Method
    methodBS Options
    opts String
    url a
    payload
      where
        methodBS :: Method
    methodBS = String -> Method
    BC8.pack String
    method

    -- | Issue a custom-method historied request with a payload
    customHistoriedPayloadMethod :: Postable a => String -> String -> a
                            -> IO (HistoriedResponse L.ByteString)

    customHistoriedPayloadMethod :: String -> String -> a -> IO (HistoriedResponse ByteString)
    customHistoriedPayloadMethod method :: String
    method url :: String
    url payload :: a
    payload =
      String
    -> Options -> String -> a -> IO (HistoriedResponse ByteString)
    forall a.
    Postable a =>
    String
    -> Options -> String -> a -> IO (HistoriedResponse ByteString)
    customHistoriedPayloadMethodWith String
    method Options
    defaults String
    url a
    payload

    -- | Issue a custom-method historied request with a paylod, using the supplied 'Options'.
    customHistoriedPayloadMethodWith :: Postable a => String -> Options -> String -> a
                            -> IO (HistoriedResponse L.ByteString)

    customHistoriedPayloadMethodWith :: String
    -> Options -> String -> a -> IO (HistoriedResponse ByteString)
    customHistoriedPayloadMethodWith method :: String
    method opts :: Options
    opts url :: String
    url payload :: a
    payload =
      RunHistory ByteString
    runReadHistory RunHistory ByteString
    -> IO Req -> IO (HistoriedResponse ByteString)
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< Method -> Options -> String -> a -> IO Req
    forall a. Postable a => Method -> Options -> String -> a -> IO Req
    preparePayloadMethod Method
    methodBS Options
    opts String
    url a
    payload
      where
        methodBS :: Method
    methodBS = String -> Method
    BC8.pack String
    method

    foldGet :: (a -> S.ByteString -> IO a) -> a -> String -> IO a
    foldGet :: (a -> Method -> IO a) -> a -> String -> IO a
    foldGet f :: a -> Method -> IO a
    f z :: a
    z url :: String
    url = Options -> (a -> Method -> IO a) -> a -> String -> IO a
    forall a. Options -> (a -> Method -> IO a) -> a -> String -> IO a
    foldGetWith Options
    defaults a -> Method -> IO a
    f a
    z String
    url

    foldGetWith :: Options -> (a -> S.ByteString -> IO a) -> a -> String -> IO a
    foldGetWith :: Options -> (a -> Method -> IO a) -> a -> String -> IO a
    foldGetWith opts :: Options
    opts f :: a -> Method -> IO a
    f z0 :: a
    z0 url :: String
    url = (Request -> IO Request)
    -> Options -> String -> (Response BodyReader -> IO a) -> IO a
    forall a.
    (Request -> IO Request)
    -> Options -> String -> (Response BodyReader -> IO a) -> IO a
    request Request -> IO Request
    forall (m :: * -> *) a. Monad m => a -> m a
    return Options
    opts String
    url ((a -> Method -> IO a) -> a -> Response BodyReader -> IO a
    forall a. (a -> Method -> IO a) -> a -> Response BodyReader -> IO a
    foldResponseBody a -> Method -> IO a
    f a
    z0)

    -- | Convert the body of an HTTP response from JSON to a suitable
    -- Haskell type.
    --
    -- In this example, we use 'asJSON' in the @IO@ monad, where it will
    -- throw a 'JSONError' exception if conversion to the desired type
    -- fails.
    --
    -- @
    -- \{-\# LANGUAGE DeriveGeneric \#-\}
    --import "GHC.Generics" ('GHC.Generics.Generic')
    --
    -- \{- This Haskell type corresponds to the structure of a
    --   response body from httpbin.org. -\}
    --
    --data GetBody = GetBody {
    --    headers :: 'Data.Map.Map' 'Data.Text.Text' 'Data.Text.Text'
    --  , args :: 'Data.Map.Map' 'Data.Text.Text' 'Data.Text.Text'
    --  , origin :: 'Data.Text.Text'
    --  , url :: 'Data.Text.Text'
    --  } deriving (Show, 'GHC.Generics.Generic')
    --
    -- \-\- Get GHC to derive a 'FromJSON' instance for us.
    --instance 'FromJSON' GetBody
    --
    -- \{- The fact that we want a GetBody below will be inferred by our
    --   use of the \"headers\" accessor function. -\}
    --
    --foo = do
    --  r <- 'asJSON' =<< 'get' \"http:\/\/httpbin.org\/get\"
    --  print (headers (r 'Control.Lens.^.' 'responseBody'))
    -- @
    --
    -- If we use 'asJSON' in the 'Either' monad, it will return 'Left'
    -- with a 'JSONError' payload if conversion fails, and 'Right' with a
    -- 'Response' whose 'responseBody' is the converted value on success.

    asJSON :: (MonadThrow m, FromJSON a) =>
              Response L.ByteString -> m (Response a)
    {-# SPECIALIZE asJSON :: (FromJSON a) =>
                             Response L.ByteString -> IO (Response a) #-}
    {-# SPECIALIZE asJSON :: Response L.ByteString -> IO (Response Aeson.Value) #-}
    asJSON :: Response ByteString -> m (Response a)
    asJSON resp :: Response ByteString
    resp = do
      let contentType :: Method
    contentType = (Method, Method) -> Method
    forall a b. (a, b) -> a
    fst ((Method, Method) -> Method)
    -> (Response ByteString -> (Method, Method))
    -> Response ByteString
    -> Method
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Word8 -> Bool) -> Method -> (Method, Method)
    S.break (Word8 -> Word8 -> Bool
    forall a. Eq a => a -> a -> Bool
    ==59) (Method -> (Method, Method))
    -> (Response ByteString -> Method)
    -> Response ByteString
    -> (Method, Method)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Method -> Maybe Method -> Method
    forall a. a -> Maybe a -> a
    fromMaybe "unknown" (Maybe Method -> Method)
    -> (Response ByteString -> Maybe Method)
    -> Response ByteString
    -> Method
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                        HeaderName -> [(HeaderName, Method)] -> Maybe Method
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup "Content-Type" ([(HeaderName, Method)] -> Maybe Method)
    -> (Response ByteString -> [(HeaderName, Method)])
    -> Response ByteString
    -> Maybe Method
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Response ByteString -> [(HeaderName, Method)]
    forall body. Response body -> [(HeaderName, Method)]
    HTTP.responseHeaders (Response ByteString -> Method) -> Response ByteString -> Method
    forall a b. (a -> b) -> a -> b
    $ Response ByteString
    resp
      Bool -> m () -> m ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    unless ("application/json" Method -> Method -> Bool
    `S.isPrefixOf` Method
    contentType
            Bool -> Bool -> Bool
    || ("application/" Method -> Method -> Bool
    `S.isPrefixOf` Method
    contentType Bool -> Bool -> Bool
    && "+json" Method -> Method -> Bool
    `S.isSuffixOf` Method
    contentType)) (m () -> m ()) -> m () -> m ()
    forall a b. (a -> b) -> a -> b
    $
        JSONError -> m ()
    forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
    throwM (JSONError -> m ()) -> (String -> JSONError) -> String -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . String -> JSONError
    JSONError (String -> m ()) -> String -> m ()
    forall a b. (a -> b) -> a -> b
    $ "content type of response is " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Method -> String
    forall a. Show a => a -> String
    show Method
    contentType
      case ByteString -> Either String a
    forall a. FromJSON a => ByteString -> Either String a
    Aeson.eitherDecode' (Response ByteString -> ByteString
    forall body. Response body -> body
    HTTP.responseBody Response ByteString
    resp) of
        Left err :: String
    err  -> JSONError -> m (Response a)
    forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
    throwM (String -> JSONError
    JSONError String
    err)
        Right val :: a
    val -> Response a -> m (Response a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((ByteString -> a) -> Response ByteString -> Response a
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (a -> ByteString -> a
    forall a b. a -> b -> a
    const a
    val) Response ByteString
    resp)

    -- | Convert the body of an HTTP response from JSON to a 'Value'.
    --
    -- In this example, we use 'asValue' in the @IO@ monad, where it will
    -- throw a 'JSONError' exception if the conversion to 'Value' fails.
    --
    -- @
    --foo = do
    --  r <- 'asValue' =<< 'get' \"http:\/\/httpbin.org\/get\"
    --  print (r 'Control.Lens.^?' 'responseBody' . key \"headers\" . key \"User-Agent\")
    -- @
    asValue :: (MonadThrow m) => Response L.ByteString -> m (Response Aeson.Value)
    {-# SPECIALIZE asValue :: Response L.ByteString
                           -> IO (Response Aeson.Value) #-}
    asValue :: Response ByteString -> m (Response Value)
    asValue = Response ByteString -> m (Response Value)
    forall (m :: * -> *) a.
    (MonadThrow m, FromJSON a) =>
    Response ByteString -> m (Response a)
    asJSON

    -- $auth
    --
    -- Do not use HTTP authentication unless you are using TLS encryption.
    -- These authentication tokens can easily be captured and reused by an
    -- attacker if transmitted in the clear.

    -- | Basic authentication. This consists of a plain username and
    -- password.
    --
    -- Example (note the use of TLS):
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.auth' '?~' 'basicAuth' \"user\" \"pass\"
    --'getWith' opts \"https:\/\/httpbin.org\/basic-auth\/user\/pass\"
    -- @
    --
    -- Note here the use of the 'Control.Lens.?~' setter to turn an 'Auth'
    -- into a 'Maybe' 'Auth', to make the type of the RHS compatible with
    -- the 'Lens.auth' lens.
    --
    -- >>> let opts = defaults & auth ?~ basicAuth "user" "pass"
    -- >>> r <- getWith opts "https://httpbin.org/basic-auth/user/pass"
    -- >>> r ^? responseBody . key "authenticated"
    -- Just (Bool True)
    basicAuth :: S.ByteString       -- ^ Username.
              -> S.ByteString       -- ^ Password.
              -> Auth
    basicAuth :: Method -> Method -> Auth
    basicAuth = Method -> Method -> Auth
    BasicAuth

    -- | OAuth1 authentication. This consists of a consumer token,
    -- a consumer secret, a token and a token secret
    oauth1Auth :: S.ByteString          -- ^ Consumer token
           -> S.ByteString          -- ^ Consumer secret
           -> S.ByteString          -- ^ OAuth token
           -> S.ByteString          -- ^ OAuth token secret
           -> Auth
    oauth1Auth :: Method -> Method -> Method -> Method -> Auth
    oauth1Auth = Method -> Method -> Method -> Method -> Auth
    OAuth1

    -- | An OAuth2 bearer token. This is treated by many services as the
    -- equivalent of a username and password.
    --
    -- Example (note the use of TLS):
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.auth' '?~' 'oauth2Bearer' \"1234abcd\"
    --'getWith' opts \"https:\/\/public-api.wordpress.com\/rest\/v1\/me\/\"
    -- @
    oauth2Bearer :: S.ByteString -> Auth
    oauth2Bearer :: Method -> Auth
    oauth2Bearer = Method -> Auth
    OAuth2Bearer

    -- | A not-quite-standard OAuth2 bearer token (that seems to be used
    -- only by GitHub). This will be treated by whatever services accept
    -- it as the equivalent of a username and password.
    --
    -- Example (note the use of TLS):
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.auth' '?~' 'oauth2Token' \"abcd1234\"
    --'getWith' opts \"https:\/\/api.github.com\/user\"
    -- @
    oauth2Token :: S.ByteString -> Auth
    oauth2Token :: Method -> Auth
    oauth2Token = Method -> Auth
    OAuth2Token

    -- | AWS v4 request signature.
    --
    -- Example (note the use of TLS):
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.auth' '?~' 'awsAuth AWSv4' \"key\" \"secret\"
    --'getWith' opts \"https:\/\/dynamodb.us-west-2.amazonaws.com\"
    -- @
    awsAuth :: AWSAuthVersion -> S.ByteString -> S.ByteString -> Auth
    awsAuth :: AWSAuthVersion -> Method -> Method -> Auth
    awsAuth version :: AWSAuthVersion
    version key :: Method
    key secret :: Method
    secret = AWSAuthVersion -> Method -> Method -> Maybe Method -> Auth
    AWSAuth AWSAuthVersion
    version Method
    key Method
    secret Maybe Method
    forall a. Maybe a
    Nothing

    -- | AWS v4 request signature using a AWS STS Session Token.
    --
    -- Example (note the use of TLS):
    --
    -- @
    --let opts = 'defaults'
    --           '&' 'Lens.auth'
    --           '?~' 'awsAuth AWSv4' \"key\" \"secret\" \"stsSessionToken\"
    --'getWith' opts \"https:\/\/dynamodb.us-west-2.amazonaws.com\"
    -- @
    awsSessionTokenAuth :: AWSAuthVersion -- ^ Signature version (V4)
                        -> S.ByteString   -- ^ AWS AccessKeyId
                        -> S.ByteString   -- ^ AWS SecretAccessKey
                        -> S.ByteString   -- ^ AWS STS SessionToken
                        -> Auth
    awsSessionTokenAuth :: AWSAuthVersion -> Method -> Method -> Method -> Auth
    awsSessionTokenAuth version :: AWSAuthVersion
    version key :: Method
    key secret :: Method
    secret sessionToken :: Method
    sessionToken =
      AWSAuthVersion -> Method -> Method -> Maybe Method -> Auth
    AWSAuth AWSAuthVersion
    version Method
    key Method
    secret (Method -> Maybe Method
    forall a. a -> Maybe a
    Just Method
    sessionToken)

    -- | AWS v4 request signature.
    --
    -- Example (note the use of TLS):
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.auth' '?~' 'awsFullAuth' 'AWSv4' \"key\" \"secret\" (Just (\"service\", \"region\"))
    --'getWith' opts \"https:\/\/dynamodb.us-west-2.amazonaws.com\"
    -- @
    awsFullAuth :: AWSAuthVersion -> S.ByteString -> S.ByteString -> Maybe S.ByteString -> Maybe (S.ByteString, S.ByteString) -> Auth
    awsFullAuth :: AWSAuthVersion
    -> Method
    -> Method
    -> Maybe Method
    -> Maybe (Method, Method)
    -> Auth
    awsFullAuth = AWSAuthVersion
    -> Method
    -> Method
    -> Maybe Method
    -> Maybe (Method, Method)
    -> Auth
    AWSFullAuth

    -- | Proxy configuration.
    --
    -- Example:
    --
    -- @
    --let opts = 'defaults' '&' 'Lens.proxy' '?~' 'httpProxy' \"localhost\" 8000
    --'getWith' opts \"http:\/\/httpbin.org\/get\"
    -- @
    --
    -- Note here the use of the 'Control.Lens.?~' setter to turn a 'Proxy'
    -- into a 'Maybe' 'Proxy', to make the type of the RHS compatible with
    -- the 'Lens.proxy' lens.
    httpProxy :: S.ByteString -> Int -> Proxy
    httpProxy :: Method -> Int -> Proxy
    httpProxy = Method -> Int -> Proxy
    Proxy

    -- | Make a 'Part' whose content is a strict 'T.Text', encoded as
    -- UTF-8.
    --
    -- The 'Part' does not have a file name or content type associated
    -- with it.
    partText :: Text             -- ^ Name of the corresponding \<input\>.
             -> Text             -- ^ The body for this 'Form.Part'.
             -> Form.Part
    partText :: Text -> Text -> Part
    partText name :: Text
    name value :: Text
    value = Text -> Method -> Part
    forall (m :: * -> *). Applicative m => Text -> Method -> PartM m
    Form.partBS Text
    name (Text -> Method
    encodeUtf8 Text
    value)

    -- | Make a 'Part' whose content is a 'String', encoded as UTF-8.
    --
    -- The 'Part' does not have a file name or content type associated
    -- with it.
    partString :: Text           -- ^ Name of the corresponding \<input\>.
               -> String         -- ^ The body for this 'Form.Part'.
               -> Form.Part
    partString :: Text -> String -> Part
    partString name :: Text
    name value :: String
    value = Text -> Method -> Part
    forall (m :: * -> *). Applicative m => Text -> Method -> PartM m
    Form.partBS Text
    name (Text -> Method
    encodeUtf8 (String -> Text
    T.pack String
    value))

    -- $session
    --
    -- The basic HTTP functions ('get', 'post', and so on) in this module
    -- have a few key drawbacks:
    --
    -- * If several requests go to the same server, there is no reuse of
    --   TCP connections.
    --
    -- * There is no management of cookies across multiple requests.
    --
    -- This makes these functions inefficient and verbose for many common
    -- uses.  For greater efficiency, use the "Network.Wreq.Session"
    -- module.

    -- $cookielenses
    --
    -- These are only the most frequently-used cookie-related lenses.  See
    -- "Network.Wreq.Lens" for the full accounting of them all.

    -- $postable
    --
    -- The 'Postable' class determines which Haskell types can be used as
    -- POST payloads.
    --
    -- 'Form.Part' and ['Form.Part'] give a request body with a
    -- @Content-Type@ of @multipart/form-data@.  Constructor functions
    -- include 'partText' and 'Form.partFile'.
    --
    -- >>> r <- post "http://httpbin.org/post" (partText "hello" "world")
    -- >>> r ^? responseBody . key "form" . key "hello"
    -- Just (String "world")
    --
    -- ('S.ByteString', 'S.ByteString') and 'FormParam' (and lists of
    -- each) give a request body with a @Content-Type@ of
    -- @application/x-www-form-urlencoded@. The easiest way to use this is
    -- via the (':=') constructor.
    --
    -- >>> r <- post "http://httpbin.org/post" ["num" := 31337, "str" := "foo"]
    -- >>> r ^? responseBody . key "form" . key "num"
    -- Just (String "31337")
    --
    -- The \"magical\" type conversion on the right-hand side of ':='
    -- above is due to the 'FormValue' class. This package provides
    -- sensible instances for the standard string and number types.
    -- You may need to explicitly add types to the values (e.g. :: String)
    -- in order to evade ambigous type errors.
    --
    -- >>> r <- post "http://httpbin.org/post" ["num" := (31337 :: Int), "str" := ("foo" :: String)]
    --
    -- The 'Aeson.Value' type gives a JSON request body with a
    -- @Content-Type@ of @application/json@. Any instance of
    -- 'Aeson.ToJSON' can of course be converted to a 'Aeson.Value' using
    -- 'Aeson.toJSON'.
    --
    -- >>> r <- post "http://httpbin.org/post" (toJSON [1,2,3])
    -- >>> r ^? responseBody . key "json" . nth 0
    -- Just (Number 1.0)

    -- $setup
    --
    -- >>> :set -XOverloadedStrings
    -- >>> import Control.Lens
    -- >>> import Data.Aeson (toJSON)
    -- >>> import Data.Aeson.Lens (key, nth)
    -- >>> import Network.Wreq