-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/

-- | An HTTP client using io-streams
--   
--   An HTTP client, using the Snap Framework's 'io-streams' library to
--   handle the streaming IO. The API is optimized for ease of use for the
--   rather common case of code needing to query web services and deal with
--   the result.
--   
--   The library is exported in a single module; see
--   Network.Http.Client for full documentation.
@package http-streams
@version 0.8.9.9

-- | Overview
--   
--   A simple HTTP client library, using the Snap Framework's
--   io-streams library to handle the streaming I/O. The
--   http-streams API is designed for ease of use when querying
--   web services and dealing with the result.
--   
--   Given:
--   
--   
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   import System.IO.Streams (InputStream, OutputStream, stdout)
--   import qualified System.IO.Streams as Streams
--   import qualified Data.ByteString as S
--   
--   
--   and this library:
--   
--   
--   import Network.Http.Client
--   
--   
--   the underlying API is straight-forward. In particular, constructing
--   the Request to send is quick and to the point:
--   
--   
--   main :: IO ()
--   main = do
--       c <- openConnection "www.example.com" 80
--   
--       let q = buildRequest1 $ do
--                   http GET "/"
--                   setAccept "text/html"
--   
--       sendRequest c q emptyBody
--   
--       receiveResponse c (\p i -> do
--           xm <- Streams.read i
--           case xm of
--               Just x    -> S.putStr x
--               Nothing   -> "")
--   
--       closeConnection c
--   
--   
--   which would print the first chunk of the response back from the
--   server. Obviously in real usage you'll do something more interesting
--   with the Response in the handler function, and consume the
--   entire response body from the InputStream ByteString.
--   
--   Because this is all happening in IO (the defining feature of
--   io-streams!), you can ensure resource cleanup on normal or
--   abnormal termination by using Control.Exception's standard
--   bracket function; see closeConnection for an example.
--   For the common case we have a utility function which wraps
--   bracket for you:
--   
--   
--   foo :: IO ByteString
--   foo = withConnection (openConnection "www.example.com" 80) doStuff
--   
--   doStuff :: Connection -> IO ByteString
--   
--   
--   There are also a set of convenience APIs that do just that, along with
--   the tedious bits like parsing URLs. For example, to do an HTTP GET and
--   stream the response body to stdout, you can simply do:
--   
--   
--   get "http://www.example.com/file.txt" (\p i -> Streams.connect i stdout)
--   
--   
--   which on the one hand is "easy" while on the other exposes the the
--   Response and InputStream for you to read from. Of course,
--   messing around with URLs is all a bit inefficient, so if you already
--   have e.g. hostname and path, or if you need more control over the
--   request being created, then the underlying http-streams API
--   is simple enough to use directly.
module Network.Http.Client
type Hostname = ByteString
type Port = Word16

-- | A connection to a web server.
data Connection

-- | In order to make a request you first establish the TCP connection to
--   the server over which to send it.
--   
--   Ordinarily you would supply the host part of the URL here and it will
--   be used as the value of the HTTP 1.1 Host: field. However,
--   you can specify any server name or IP addresss and set the
--   Host: value later with setHostname when building the
--   request.
--   
--   Usage is as follows:
--   
--   
--   c <- openConnection "localhost" 80
--   ...
--   closeConnection c
--   
--   
--   More likely, you'll use withConnection to wrap the call in
--   order to ensure finalization.
--   
--   HTTP pipelining is supported; you can reuse the connection to a web
--   server, but it's up to you to ensure you match the number of requests
--   sent to the number of responses read, and to process those responses
--   in order. This is all assuming that the server supports
--   pipelining; be warned that not all do. Web browsers go to
--   extraordinary lengths to probe this; you probably only want to do
--   pipelining under controlled conditions. Otherwise just open a new
--   connection for subsequent requests.
openConnection :: Hostname -> Port -> IO Connection

-- | Open a connection to a Unix domain socket.
--   
--   
--   main :: IO ()
--   main = do
--       c <- openConnectionUnix "/var/run/docker.sock"
--       ...
--       closeConnection c
--   
openConnectionUnix :: FilePath -> IO Connection

-- | HTTP Methods, as per RFC 2616
data Method
GET :: Method
HEAD :: Method
POST :: Method
PUT :: Method
DELETE :: Method
TRACE :: Method
OPTIONS :: Method
CONNECT :: Method
PATCH :: Method
Method :: ByteString -> Method

-- | The RequestBuilder monad allows you to abuse do-notation to
--   conveniently setup a Request object.
data RequestBuilder α

-- | Run a RequestBuilder, yielding a Request object you can use on the
--   given connection.
--   
--   
--   let q = buildRequest1 $ do
--               http POST "/api/v1/messages"
--               setContentType "application/json"
--               setHostname "clue.example.com" 80
--               setAccept "text/html"
--               setHeader "X-WhoDoneIt" "The Butler"
--   
--   
--   Obviously it's up to you to later actually send JSON data.
buildRequest1 :: RequestBuilder α -> Request

-- | Run a RequestBuilder from within a monadic action.
--   
--   Older versions of this library had buildRequest in IO; there's
--   no longer a need for that, but this code path will continue to work
--   for existing users.
--   
--   
--   q <- buildRequest $ do
--            http GET "/"
--   
buildRequest :: Monad ν => RequestBuilder α -> ν Request

-- | Begin constructing a Request, starting with the request line.
http :: Method -> ByteString -> RequestBuilder ()

-- | Set the [virtual] hostname for the request. In ordinary conditions you
--   won't need to call this, as the Host: header is a required
--   header in HTTP 1.1 and is set directly from the name of the server you
--   connected to when calling openConnection.
setHostname :: Hostname -> Port -> RequestBuilder ()

-- | Indicate the content type you are willing to receive in a reply from
--   the server. For more complex Accept: headers, use
--   setAccept'.
setAccept :: ByteString -> RequestBuilder ()

-- | Indicate the content types you are willing to receive in a reply from
--   the server in order of preference. A call of the form:
--   
--   
--   setAccept' [("text/html", 1.0),
--               ("application/xml", 0.8),
--               ("*/*", 0)]
--   
--   
--   will result in an Accept: header value of text/html;
--   q=1.0, application/xml; q=0.8, */*; q=0.0 as you would expect.
setAccept' :: [(ByteString, Float)] -> RequestBuilder ()

-- | Set username and password credentials per the HTTP basic
--   authentication method.
--   
--   
--   setAuthorizationBasic "Aladdin" "open sesame"
--   
--   
--   will result in an Authorization: header value of Basic
--   QWxhZGRpbjpvcGVuIHNlc2FtZQ==.
--   
--   Basic authentication does not use a message digest function to
--   encipher the password; the above string is only base-64 encoded and is
--   thus plain-text visible to any observer on the wire and all caches and
--   servers at the other end, making basic authentication completely
--   insecure. A number of web services, however, use SSL to encrypt the
--   connection that then use HTTP basic authentication to validate
--   requests. Keep in mind in these cases the secret is still sent to the
--   servers on the other side and passes in clear through all layers after
--   the SSL termination. Do not use basic authentication to protect
--   secure or user-originated privacy-sensitve information.
setAuthorizationBasic :: ByteString -> ByteString -> RequestBuilder ()
type ContentType = ByteString

-- | Set the MIME type corresponding to the body of the request you are
--   sending. Defaults to "text/plain", so usually you need to set
--   this if PUTting.
setContentType :: ContentType -> RequestBuilder ()

-- | Specify the length of the request body, in bytes.
--   
--   RFC 2616 requires that we either send a Content-Length header
--   or use Transfer-Encoding: chunked. If you know the exact size
--   ahead of time, then call this function; the body content will still be
--   streamed out by io-streams in more-or-less constant space.
--   
--   This function is special: in a PUT or POST request,
--   http-streams will assume chunked transfer-encoding
--   unless you specify a content length here, in which case you
--   need to ensure your body function writes precisely that many bytes.
setContentLength :: Int64 -> RequestBuilder ()
type FieldName = ByteString
data Boundary

-- | Generate a random string to be used as an inter-part boundary in RFC
--   7578 multipart form data. You pass this value to
--   setContentMultipart and subsequently to
--   multipartFormBody.
randomBoundary :: IO Boundary

-- | If sending multipart form data (RFC 7578), you need to set the MIME
--   type to "multipart/form-data" and specify the boundary
--   separator that will be used.
--   
--   This function is special: you must subsequently use
--   multipartFormBody to sequence the individual body parts. When
--   sending the request it will separate the individual parts by the
--   boundary value set by this function.
setContentMultipart :: Boundary -> RequestBuilder ()

-- | Specify that this request should set the expectation that the server
--   needs to approve the request before you send it.
--   
--   This function is special: in a PUT or POST request,
--   http-streams will wait for the server to reply with an
--   HTTP/1.1 100 Continue status before sending the entity body. This is
--   handled internally; you will get the real response (be it successful
--   2xx, client error, 4xx, or server error 5xx) in
--   receiveResponse. In theory, it should be 417 if the
--   expectation failed.
--   
--   Only bother with this if you know the service you're talking to
--   requires clients to send an Expect: 100-continue header and
--   will handle it properly. Most servers don't do any precondition
--   checking, automatically send an intermediate 100 response, and then
--   just read the body regardless, making this a bit of a no-op in most
--   cases.
setExpectContinue :: RequestBuilder ()

-- | Override the default setting about how the entity body will be sent.
--   
--   This function is special: this explicitly sets the
--   Transfer-Encoding: header to chunked and will
--   instruct the library to actually tranfer the body as a stream
--   ("chunked transfer encoding"). See setContentLength for forcing
--   the opposite. You really won't need this in normal operation,
--   but some people are control freaks.
setTransferEncoding :: RequestBuilder ()

-- | Set a generic header to be sent in the HTTP request. The other methods
--   in the RequestBuilder API are expressed in terms of this function, but
--   we recommend you use them where offered for their stronger types.
setHeader :: ByteString -> ByteString -> RequestBuilder ()

-- | A description of the request that will be sent to the server. Note
--   unlike other HTTP libraries, the request body is not a part of
--   this object; that will be streamed out by you when actually sending
--   the request with sendRequest.
--   
--   Request has a useful Show instance that will output
--   the request line and headers (as it will be sent over the wire but
--   with the \r characters stripped) which can be handy for
--   debugging.
--   
--   Note that the actual Host: header is not set until the
--   request is sent, so you will not see it in the Show instance (unless
--   you call setHostname to override the value inherited from the
--   Connection).
data Request

-- | A description of the response received from the server. Note unlike
--   other HTTP libraries, the response body is not a part of this
--   object; that will be streamed in by you when calling
--   receiveResponse.
--   
--   Like Request, Response has a Show instance that
--   will output the status line and response headers as they were received
--   from the server.
data Response

-- | Get the virtual hostname that will be used as the Host:
--   header in the HTTP 1.1 request. Per RFC 2616 § 14.23, this will be of
--   the form hostname:port if the port number is other than the
--   default, ie 80 for HTTP.
getHostname :: Connection -> Request -> ByteString

-- | Having composed a Request object with the headers and metadata
--   for this connection, you can now send the request to the server, along
--   with the entity body, if there is one. For the rather common case of
--   HTTP requests like GET that don't send data, use
--   emptyBody as the output stream:
--   
--   
--   sendRequest c q emptyBody
--   
--   
--   For PUT and POST requests, you can use fileBody
--   or inputStreamBody to send content to the server, or you can
--   work with the io-streams API directly:
--   
--   
--   sendRequest c q (\o ->
--       Streams.write (Just (Builder.fromString "Hello World\n")) o)
--   
sendRequest :: Connection -> Request -> (OutputStream Builder -> IO α) -> IO α

-- | Use this for the common case of the HTTP methods that only send
--   headers and which have no entity body, i.e. GET requests.
emptyBody :: OutputStream Builder -> IO ()

-- | Sometimes you just want to send some bytes to the server as a the body
--   of your request. This is easy to use, but if you're doing anything
--   massive use inputStreamBody; if you're sending a file use
--   fileBody; if you have an object that needs to be sent as JSON
--   use jsonBody
simpleBody :: ByteString -> OutputStream Builder -> IO ()

-- | Specify a local file to be sent to the server as the body of the
--   request.
--   
--   You use this partially applied:
--   
--   
--   sendRequest c q (fileBody "/etc/passwd")
--   
--   
--   Note that the type of (fileBody "/path/to/file") is just what
--   you need for the third argument to sendRequest, namely
--   
--   
--   >>> :t filePath "hello.txt"
--   :: OutputStream Builder -> IO ()
--   
fileBody :: FilePath -> OutputStream Builder -> IO ()

-- | Read from a pre-existing InputStream and pipe that through to
--   the connection to the server. This is useful in the general case where
--   something else has handed you stream to read from and you want to use
--   it as the entity body for the request.
--   
--   You use this partially applied:
--   
--   
--   i <- getStreamFromVault                    -- magic, clearly
--   sendRequest c q (inputStreamBody i)
--   
--   
--   This function maps "Builder.fromByteString" over the input, which will
--   be efficient if the ByteString chunks are large.
inputStreamBody :: InputStream ByteString -> OutputStream Builder -> IO ()

-- | Specify name/value pairs to be sent to the server in the manner used
--   by web browsers when submitting a form via a POST request. Parameters
--   will be URL encoded per RFC 2396 and combined into a single string
--   which will be sent as the body of your request.
--   
--   You use this partially applied:
--   
--   
--   let nvs = [("name","Kermit"),
--              ("type","frog")]
--              ("role","stagehand")]
--   
--   sendRequest c q (encodedFormBody nvs)
--   
--   
--   Note that it's going to be up to you to call setContentType
--   with a value of "application/x-www-form-urlencoded" when
--   building the Request object; the postForm convenience (which
--   uses this encodedFormBody function) takes care of this for
--   you, obviously.
encodedFormBody :: [(ByteString, ByteString)] -> OutputStream Builder -> IO ()

-- | Build a list of parts into an upload body.
--   
--   You use this partially applied:
--   
--   
--   boundary <- randomBoundary
--   
--   let q = buildRequest1 $ do
--         http POST "/api/v1/upload"
--         setContentMultipart boundary
--   
--   let parts =
--           [ simplePart "metadata" Nothing metadata
--           , filePart "submission" (Just "audio/wav") filepath
--           ]
--   
--   sendRequest c q (multipartFormBody boundary parts)
--   
--   
--   You must have called setContentMultipart when forming
--   the request or the request body you are sending will be invalid and
--   (obviously) you must pass in that same Boundary value when
--   calling this function.
multipartFormBody :: Boundary -> [Part] -> OutputStream Builder -> IO ()

-- | Information about each of the parts of a multipart/form-data
--   form upload. Build these with simplePart, filePart, or
--   inputStreamPart.
data Part

-- | Given a simple static set of bytes, send them as a part in a multipart
--   form upload. You need to specify the name of the field for the form,
--   and optionally can supply a MIME content-type.
simplePart :: FieldName -> Maybe ContentType -> ByteString -> Part

-- | The most common case in using multipart form data is to upload a file.
--   Specify the name of the field, optionally a MIME content-type, and
--   then the path to the file to be transmitted. The filename (without
--   directory) will be used to name the file to the server.
filePart :: FieldName -> Maybe ContentType -> FilePath -> Part

-- | Build a piece of a multipart submission from an InputStream.
--   You need to specify a field name for this piece of the submission, and
--   can optionally indicate the MIME type and a filename (if what you are
--   sending is going to be interpreted as a file).
inputStreamPart :: FieldName -> Maybe ContentType -> Maybe FilePath -> InputStream ByteString -> Part

-- | If you've got an object of a type with a ToJSON instance and
--   you need to send that object as JSON up to a web service API, this can
--   help.
--   
--   You use this partially applied:
--   
--   
--   sendRequest c q (jsonBody thing)
--   
jsonBody :: ToJSON a => a -> OutputStream Builder -> IO ()

-- | Handle the response coming back from the server. This function hands
--   control to a handler function you supply, passing you the
--   Response object with the response headers and an
--   InputStream containing the entity body.
--   
--   For example, if you just wanted to print the first chunk of the
--   content from the server:
--   
--   
--   receiveResponse c (\p i -> do
--       m <- Streams.read i
--       case m of
--           Just bytes -> putStr bytes
--           Nothing    -> return ())
--   
--   
--   Obviously, you can do more sophisticated things with the
--   InputStream, which is the whole point of having an
--   io-streams based HTTP client library.
--   
--   The final value from the handler function is the return value of
--   receiveResponse, if you need it.
--   
--   Throws UnexpectedCompression if it doesn't know how to handle
--   the compression format used in the response.
receiveResponse :: Connection -> (Response -> InputStream ByteString -> IO β) -> IO β

-- | This is a specialized variant of receiveResponse that
--   explicitly does not handle the content encoding of the response
--   body stream (it will not decompress anything). Unless you really want
--   the raw gzipped content coming down from the server, use
--   receiveResponse.
receiveResponseRaw :: Connection -> (Response -> InputStream ByteString -> IO β) -> IO β

-- | Handle the response coming back from the server. This function is the
--   same as receiveResponse, but it does not consume the body for you
--   after the handler is done. This means that it can only be safely used
--   if the handler will fully consume the body, there is no body, or when
--   the connection is not being reused (no pipelining).
unsafeReceiveResponse :: Connection -> (Response -> InputStream ByteString -> IO β) -> IO β
data UnexpectedCompression
type StatusCode = Int

-- | Get the HTTP response status code.
getStatusCode :: Response -> StatusCode

-- | Get the HTTP response status message. Keep in mind that this is
--   not normative; whereas getStatusCode values are
--   authoritative.
getStatusMessage :: Response -> ByteString

-- | Lookup a header in the response. HTTP header field names are
--   case-insensitive, so you can specify the name to lookup however you
--   like. If the header is not present Nothing will be returned.
--   
--   
--   let n = case getHeader p "Content-Length" of
--              Just x' -> read x' :: Int
--              Nothing -> 0
--   
--   
--   which of course is essentially what goes on inside the client library
--   when it receives a response from the server and has to figure out how
--   many bytes to read.
--   
--   There is a fair bit of complexity in some of the other HTTP response
--   fields, so there are a number of specialized functions for reading
--   those values where we've found them useful.
getHeader :: Response -> ByteString -> Maybe ByteString

-- | Print the response headers and response body to stdout. You
--   can use this with receiveResponse or one of the convenience
--   functions when testing. For example, doing:
--   
--   
--   c <- openConnection "kernel.operationaldynamics.com" 58080
--   
--   let q = buildRequest1 $ do
--               http GET "/time"
--   
--   sendRequest c q emptyBody
--   
--   receiveResponse c debugHandler
--   
--   
--   would print out:
--   
--   
--   HTTP/1.1 200 OK
--   Transfer-Encoding: chunked
--   Content-Type: text/plain
--   Vary: Accept-Encoding
--   Server: Snap/0.9.2.4
--   Content-Encoding: gzip
--   Date: Mon, 21 Jan 2013 06:13:37 GMT
--   
--   Mon 21 Jan 13, 06:13:37.303Z
--   
--   
--   or thereabouts.
debugHandler :: Response -> InputStream ByteString -> IO ()

-- | Sometimes you just want the entire response body as a single blob.
--   This function concatonates all the bytes from the response into a
--   ByteString. If using the main http-streams API, you would use
--   it as follows:
--   
--   
--   ...
--   x' <- receiveResponse c simpleHandler
--   ...
--   
--   
--   The methods in the convenience API all take a function to handle the
--   response; this function is passed directly to the
--   receiveResponse call underlying the request. Thus this utility
--   function can be used for get as well:
--   
--   
--   x' <- get "http://www.example.com/document.txt" simpleHandler
--   
--   
--   Either way, the usual caveats about allocating a single object from
--   streaming I/O apply: do not use this if you are not absolutely certain
--   that the response body will fit in a reasonable amount of memory.
--   
--   Note that this function makes no discrimination based on the
--   response's HTTP status code. You're almost certainly better off
--   writing your own handler function.
simpleHandler :: Response -> InputStream ByteString -> IO ByteString

-- | A special case of concatHandler, this function will return the
--   entire response body as a single ByteString, but will throw
--   HttpClientError if the response status code was other than
--   2xx.
simpleHandler' :: Response -> InputStream ByteString -> IO ByteString
data HttpClientError
HttpClientError :: Int -> ByteString -> HttpClientError

-- | If you're working with a data stream that is in
--   application/json, then chances are you're using
--   aeson to handle the JSON to Haskell decoding. If so, then
--   this helper function might be of use.
--   
--   
--   v <- get "http://api.example.com/v1/" jsonHandler
--   
--   
--   This function feeds the input body to the json'
--   attoparsec Parser in order to get the aeson Value type. This
--   is then marshalled to your type represeting the source data, via the
--   FromJSON typeclass.
--   
--   The above example was actually insufficient; when working with
--   aeson you need to fix the type so it knows what FromJSON
--   instance to use. Let's say you're getting Person objects, then it
--   would be
--   
--   
--   v <- get "http://api.example.com/v1/person/461" jsonHandler :: IO Person
--   
--   
--   assuming your Person type had a FromJSON instance, of course.
--   
--   Note
--   
--   This function parses a single top level JSON object or array, which is
--   all you're supposed to get if it's a valid document. People do all
--   kinds of crazy things though, so beware. Also, this function (like the
--   "concatHander" convenience) loads the entire response into memory;
--   it's not streaming; if you're receiving a document which is
--   (say) a very long array of objects then you may want to implement your
--   own handler function, perhaps using "Streams.parserToInputStream" and
--   the Parser combinators directly — with a result type of
--   InputStream Value, perhaps — by which you could then iterate over the
--   Values one at a time in constant space.
jsonHandler :: FromJSON α => Response -> InputStream ByteString -> IO α

-- | Shutdown the connection. You need to call this release the underlying
--   socket file descriptor and related network resources. To do so
--   reliably, use this in conjunction with openConnection in a call
--   to bracket:
--   
--   
--   --
--   -- Make connection, cleaning up afterward
--   --
--   
--   foo :: IO ByteString
--   foo = bracket
--      (openConnection "localhost" 80)
--      (closeConnection)
--      (doStuff)
--   
--   --
--   -- Actually use Connection to send Request and receive Response
--   --
--   
--   doStuff :: Connection -> IO ByteString
--   
--   
--   or, just use withConnection.
--   
--   While returning a ByteString is probably the most common use case, you
--   could conceivably do more processing of the response in
--   doStuff and have it and foo return a different type.
closeConnection :: Connection -> IO ()

-- | Given an IO action producing a Connection, and a
--   computation that needs one, runs the computation, cleaning up the
--   Connection afterwards.
--   
--   
--   x <- withConnection (openConnection "s3.example.com" 80) $ (\c -> do
--       let q = buildRequest1 $ do
--           http GET "/bucket42/object/149"
--       sendRequest c q emptyBody
--       ...
--       return "blah")
--   
--   
--   which can make the code making an HTTP request a lot more
--   straight-forward.
--   
--   Wraps Control.Exception's bracket.
withConnection :: IO Connection -> (Connection -> IO γ) -> IO γ
type URL = ByteString

-- | Issue an HTTP GET request and pass the resultant response to the
--   supplied handler function. This code will silently follow redirects,
--   to a maximum depth of 5 hops.
--   
--   The handler function is as for receiveResponse, so you can use
--   one of the supplied convenience handlers if you're in a hurry:
--   
--   
--   x' <- get "http://www.bbc.co.uk/news/" concatHandler
--   
--   
--   But as ever the disadvantage of doing this is that you're not doing
--   anything intelligent with the HTTP response status code. If you want
--   an exception raised in the event of a non 2xx response, you
--   can use:
--   
--   
--   x' <- get "http://www.bbc.co.uk/news/" concatHandler'
--   
--   
--   but for anything more refined you'll find it easy to simply write your
--   own handler function.
--   
--   Throws TooManyRedirects if more than 5 redirects are thrown.
get :: URL -> (Response -> InputStream ByteString -> IO β) -> IO β
data TooManyRedirects

-- | Send content to a server via an HTTP POST request. Use this function
--   if you have an OutputStream with the body content.
post :: URL -> ContentType -> (OutputStream Builder -> IO α) -> (Response -> InputStream ByteString -> IO β) -> IO β

-- | Send form data to a server via an HTTP POST request. This is the usual
--   use case; most services expect the body to be MIME type
--   application/x-www-form-urlencoded as this is what
--   conventional web browsers send on form submission. If you want to POST
--   to a URL with an arbitrary Content-Type, use post.
postForm :: URL -> [(ByteString, ByteString)] -> (Response -> InputStream ByteString -> IO β) -> IO β

-- | Place content on the server at the given URL via an HTTP PUT request,
--   specifying the content type and a function to write the content to the
--   supplied OutputStream. You might see:
--   
--   
--   put "http://s3.example.com/bucket42/object149" "text/plain"
--       (fileBody "hello.txt") (\p i -> do
--           putStr $ show p
--           Streams.connect i stdout)
--   
put :: URL -> ContentType -> (OutputStream Builder -> IO α) -> (Response -> InputStream ByteString -> IO β) -> IO β

-- | Open a secure connection to a web server.
--   
--   
--   import OpenSSL (withOpenSSL)
--   
--   main :: IO ()
--   main = do
--       ctx <- baselineContextSSL
--       c <- openConnectionSSL ctx "api.github.com" 443
--       ...
--       closeConnection c
--   
--   
--   If you want to tune the parameters used in making SSL connections,
--   manually specify certificates, etc, then setup your own context:
--   
--   
--   import OpenSSL.Session (SSLContext)
--   import qualified OpenSSL.Session as SSL
--   
--       ...
--       ctx <- SSL.context
--       ...
--   
--   
--   See OpenSSL.Session.
--   
--   Crypto is as provided by the system openssl library, as
--   wrapped by the HsOpenSSL package and
--   openssl-streams.
--   
--   /There is no longer a need to call withOpenSSL explicitly;
--   the initialization is invoked once per process for you/
openConnectionSSL :: SSLContext -> Hostname -> Port -> IO Connection

-- | Creates a basic SSL context. This is the SSL context used if you make
--   an "https://" request using one of the convenience functions.
--   It configures OpenSSL to use the default set of ciphers.
--   
--   On Linux, OpenBSD and FreeBSD systems, this function also configures
--   OpenSSL to verify certificates using the system/distribution supplied
--   certificate authorities' certificates
--   
--   On other systems, no certificate validation is performed by the
--   generated SSLContext because there is no canonical place to
--   find the set of system certificates. When using this library on such
--   system, you are encouraged to install the system certificates
--   somewhere and create your own SSLContext.
baselineContextSSL :: IO SSLContext

-- | Modify the context being used to configure the SSL tunnel used by the
--   convenience API functions to make https:// connections. The
--   default is that setup by baselineContextSSL.
modifyContextSSL :: (SSLContext -> IO SSLContext) -> IO ()

-- | Given a URL, work out whether it is normal, secure, or unix domain,
--   and then open the connection to the webserver including setting the
--   appropriate default port if one was not specified in the URL. This is
--   what powers the convenience API, but you may find it useful in
--   composing your own similar functions.
--   
--   For example (on the assumption that your server behaves when given an
--   absolute URI as the request path), this will open a connection to
--   server www.example.com port 443 and request
--   /photo.jpg:
--   
--   
--   let url = "https://www.example.com/photo.jpg"
--   
--   c <- establishConnection url
--   let q = buildRequest1 $ do
--               http GET url
--   ...
--   
establishConnection :: URL -> IO Connection

-- | Create a raw Connection object from the given parts. This is primarily
--   of use when teseting, for example:
--   
--   
--   fakeConnection :: IO Connection
--   fakeConnection = do
--       o  <- Streams.nullOutput
--       i  <- Streams.nullInput
--       c  <- makeConnection "www.example.com" (return()) o i
--       return c
--   
--   
--   is an idiom we use frequently in testing and benchmarking, usually
--   replacing the InputStream with something like:
--   
--   
--   x' <- S.readFile "properly-formatted-response.txt"
--   i  <- Streams.fromByteString x'
--   
--   
--   If you're going to do that, keep in mind that you must have
--   CR-LF pairs after each header line and between the header and body to
--   be compliant with the HTTP protocol; otherwise, parsers will reject
--   your message.
makeConnection :: ByteString -> IO () -> OutputStream ByteString -> InputStream ByteString -> IO Connection

-- | The map of headers in a Request or Response. Note that
--   HTTP header field names are case insensitive, so if you call
--   setHeader on a field that's already defined but with a
--   different capitalization you will replace the existing value.
data Headers

-- | Get the Headers from a Request or Response.y
getHeaders :: HttpType τ => τ -> Headers

-- | Get the headers that will be sent with this request. You likely won't
--   need this but there are some corner cases where people need to make
--   calculations based on all the headers before they go out over the
--   wire.
--   
--   If you'd like the request headers as an association list, import the
--   header functions:
--   
--   
--   import Network.Http.Types
--   
--   
--   then use retreiveHeaders as follows:
--   
--   
--   >>> let kvs = retreiveHeaders $ getHeadersFull c q
--   
--   >>> :t kvs
--   :: [(ByteString, ByteString)]
--   
getHeadersFull :: Connection -> Request -> Headers

-- | If you want to fix the multipart boundary to a known value (for
--   testing purposes) you can use this. The ideal such string, in case you
--   are wondering, is "bEacHV0113YB@ll".
--   
--   This isn't safe for use in production; you need to use an
--   unpredictable value as the boundary separtor so prefer
--   randomBoundary.
packBoundary :: String -> Boundary

-- | Deprecated: Use simpleHandler instead
concatHandler :: Response -> InputStream ByteString -> IO ByteString
concatHandler' :: Response -> InputStream ByteString -> IO ByteString

-- | Deprecated: use retrieveHeaders . getHeadersFull instead
getRequestHeaders :: Connection -> Request -> [(ByteString, ByteString)]
