Safe Haskell | None |
---|---|
Language | Haskell2010 |
Basic types used in HTTP communications. This modules is re-exported by both Network.Http.Client and Pipes.Http.Client, so if you're using either of those you don't need to explicitly import this module.
- type Hostname = ByteString
- type Port = Word16
- data Request
- data EntityBody
- data ExpectMode
- data RequestBuilder α
- buildRequest :: Monad ν => RequestBuilder α -> ν Request
- buildRequest1 :: RequestBuilder α -> Request
- http :: Method -> ByteString -> RequestBuilder ()
- setHostname :: Hostname -> Port -> RequestBuilder ()
- setAccept :: ByteString -> RequestBuilder ()
- setAccept' :: [(ByteString, Float)] -> RequestBuilder ()
- setAuthorizationBasic :: ByteString -> ByteString -> RequestBuilder ()
- type ContentType = ByteString
- setContentType :: ContentType -> RequestBuilder ()
- setContentLength :: Int64 -> RequestBuilder ()
- setExpectContinue :: RequestBuilder ()
- setTransferEncoding :: RequestBuilder ()
- setHeader :: ByteString -> ByteString -> RequestBuilder ()
- data Response
- type StatusCode = Int
- data TransferEncoding
- data ContentEncoding
- getStatusCode :: Response -> StatusCode
- getStatusMessage :: Response -> ByteString
- getHeader :: Response -> ByteString -> Maybe ByteString
- data Method
- data Headers
- emptyHeaders :: Headers
- updateHeader :: Headers -> ByteString -> ByteString -> Headers
- removeHeader :: Headers -> ByteString -> Headers
- buildHeaders :: [(ByteString, ByteString)] -> Headers
- lookupHeader :: Headers -> ByteString -> Maybe ByteString
- retrieveHeaders :: Headers -> [(ByteString, ByteString)]
- class HttpType τ where
- getHeaders :: τ -> Headers
- data HttpParseException = HttpParseException String
Requests
type Hostname = ByteString Source
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 RequestBuilder α Source
The RequestBuilder monad allows you to abuse do-notation to
conveniently setup a Request
object.
buildRequest :: Monad ν => RequestBuilder α -> ν Request Source
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 "/"
buildRequest1 :: RequestBuilder α -> Request Source
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.
http :: Method -> ByteString -> RequestBuilder () Source
Begin constructing a Request, starting with the request line.
setHostname :: Hostname -> Port -> RequestBuilder () Source
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
.
setAccept :: ByteString -> RequestBuilder () Source
Indicate the content type you are willing to receive in a reply
from the server. For more complex Accept:
headers, use
setAccept'
.
setAccept' :: [(ByteString, Float)] -> RequestBuilder () Source
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.
setAuthorizationBasic :: ByteString -> ByteString -> RequestBuilder () Source
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.
type ContentType = ByteString Source
setContentType :: ContentType -> RequestBuilder () Source
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 PUT
ting.
setContentLength :: Int64 -> RequestBuilder () Source
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.
setExpectContinue :: RequestBuilder () Source
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.
setTransferEncoding :: RequestBuilder () Source
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.
setHeader :: ByteString -> ByteString -> RequestBuilder () Source
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.
Responses
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.
type StatusCode = Int Source
getStatusCode :: Response -> StatusCode Source
Get the HTTP response status code.
getStatusMessage :: Response -> ByteString Source
Get the HTTP response status message. Keep in mind that this is
not normative; whereas getStatusCode
values are authoritative.
getHeader :: Response -> ByteString -> Maybe ByteString Source
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.
HTTP Methods, as per RFC 2616
Headers
updateHeader :: Headers -> ByteString -> ByteString -> Headers Source
Set a header field to the specified value. This will overwrite any existing value for the field. Remember that HTTP fields names are case insensitive!
removeHeader :: Headers -> ByteString -> Headers Source
Remove a header from the map. If a field with that name is not present, then this will have no effect.
buildHeaders :: [(ByteString, ByteString)] -> Headers Source
Given a list of field-name,field-value pairs, construct a Headers map.
lookupHeader :: Headers -> ByteString -> Maybe ByteString Source
retrieveHeaders :: Headers -> [(ByteString, ByteString)] Source
Get the headers as a field-name,field-value association list.
Accessors common to both the outbound and return sides of an HTTP connection.
getHeaders :: τ -> Headers Source
Get the Headers from a Request or Response. Most people do not need
this; for most cases you just need to get a header or two from the
response, for which you can use getHeader
. On the other hand, if you
do need to poke around in the raw headers,
import Network.Http.Types
will give you functions like lookupHeader
and updateHeader
to to
work with.