HTTP-0.4ContentsIndex
Network.HTTP
Portabilitynon-portable (not tested)
Stabilityexperimental
Maintainerbjorn@bringert.net
Contents
Type declarations
Streams
Connections
HTTP
Header Functions
URL Encoding
URI authority parsing
Description

An easy HTTP interface enjoy.

  • Changes by Graham Klyne: - export httpVersion - use new URI module (similar to old, but uses revised URI datatype)
  • Changes by Bjorn Bringert:
  • handle URIs with a port number - added debugging toggle - disabled 100-continue transfers to get HTTP/1.0 compatibility - change ioError to throw
  • Changes from 0.1 - change openHTTP to openTCP, removed closeTCP - use close from Stream class. - added use of inet_addr to openHTTP, allowing use of IP dot notation addresses. - reworking of the use of Stream, including alterations to make sendHTTP generic and the addition of a debugging stream. - simplified error handling.
  • TODO - request pipelining - https upgrade (includes full TLS, i.e. SSL, implementation) - use of Stream classes will pay off - consider C implementation of encryption/decryption - comm timeouts - MIME & entity stuff (happening in separate module) - support "*" uri-request-string for OPTIONS request method
  • Header notes:
Host
Required by HTTP/1.1, if not supplied as part of a request a default Host value is extracted from the request-uri.
Connection
If this header is present in any request or response, and it's value is close, then the current request/response is the last to be allowed on that connection.
Expect
Should a request contain a body, an Expect header will be added to the request. The added header has the value "100-continue". After a 417 "Expectation Failed" response the request is attempted again without this added Expect header.
TransferEncoding,ContentLength,...
if request is inconsistent with any of these header values then you may not receive any response or will generate an error response (probably 4xx).
  • Response code notes Some response codes induce special behaviour:
1xx
"100 Continue" will cause any unsent request body to be sent. "101 Upgrade" will be returned. Other 1xx responses are ignored.
417
The reason for this code is "Expectation failed", indicating that the server did not like the Expect "100-continue" header added to a request. Receipt of 417 will induce another request attempt (without Expect header), unless no Expect header had been added (in which case 417 response is returned).
Synopsis
httpVersion :: String
data Debug x
class Stream x where
readLine :: x -> IO (Result String)
readBlock :: x -> Int -> IO (Result String)
writeBlock :: x -> String -> IO (Result ())
close :: x -> IO ()
debugStream :: Stream a => String -> a -> IO (Debug a)
data Connection
data ConnError
= ErrorReset
| ErrorClosed
| ErrorParse String
| ErrorMisc String
openTCP :: String -> IO Connection
isConnectedTo :: Connection -> String -> IO Bool
data Request = Request {
rqURI :: URI
rqMethod :: RequestMethod
rqHeaders :: [Header]
rqBody :: String
}
data Response = Response {
rspCode :: ResponseCode
rspReason :: String
rspHeaders :: [Header]
rspBody :: String
}
data RequestMethod
= HEAD
| PUT
| GET
| POST
| OPTIONS
| TRACE
simpleHTTP :: Request -> IO (Result Response)
sendHTTP :: Stream s => s -> Request -> IO (Result Response)
class HasHeaders x
data Header = Header HeaderName String
data HeaderName
= HdrCacheControl
| HdrConnection
| HdrDate
| HdrPragma
| HdrTransferEncoding
| HdrUpgrade
| HdrVia
| HdrAccept
| HdrAcceptCharset
| HdrAcceptEncoding
| HdrAcceptLanguage
| HdrAuthorization
| HdrCookie
| HdrExpect
| HdrFrom
| HdrHost
| HdrIfModifiedSince
| HdrIfMatch
| HdrIfNoneMatch
| HdrIfRange
| HdrIfUnmodifiedSince
| HdrMaxForwards
| HdrProxyAuthorization
| HdrRange
| HdrReferer
| HdrUserAgent
| HdrAge
| HdrLocation
| HdrProxyAuthenticate
| HdrPublic
| HdrRetryAfter
| HdrServer
| HdrSetCookie
| HdrVary
| HdrWarning
| HdrWWWAuthenticate
| HdrAllow
| HdrContentBase
| HdrContentEncoding
| HdrContentLanguage
| HdrContentLength
| HdrContentLocation
| HdrContentMD5
| HdrContentRange
| HdrContentType
| HdrETag
| HdrExpires
| HdrLastModified
| HdrContentTransferEncoding
| HdrCustom String
insertHeader :: HasHeaders a => HeaderName -> String -> a -> a
insertHeaderIfMissing :: HasHeaders a => HeaderName -> String -> a -> a
insertHeaders :: HasHeaders a => [Header] -> a -> a
retrieveHeaders :: HasHeaders a => HeaderName -> a -> [Header]
replaceHeader :: HasHeaders a => HeaderName -> String -> a -> a
urlEncode :: String -> String
urlDecode :: String -> String
urlEncodeVars :: [(String, String)] -> String
data URIAuthority = URIAuthority {
user :: (Maybe String)
password :: (Maybe String)
host :: String
port :: (Maybe Int)
}
parseURIAuthority :: String -> Maybe URIAuthority
Documentation
httpVersion :: String
Type declarations
Streams
data Debug x
Allows stream logging. Refer to debugStream below.
show/hide Instances
class Stream x where

Streams should make layering of TLS protocol easier in future, they allow readingwriting to files etc for debugging, they allow use of protocols other than TCPIP and they allow customisation.

Instances of this class should not trim the input in any way, e.g. leave LF on line endings etc. Unless that is exactly the behaviour you want from your twisted instances ;)

Methods
readLine :: x -> IO (Result String)
readBlock :: x -> Int -> IO (Result String)
writeBlock :: x -> String -> IO (Result ())
close :: x -> IO ()
show/hide Instances
debugStream :: Stream a => String -> a -> IO (Debug a)
Wraps a stream with logging I/O, the first argument is a filename which is opened in AppendMode.
Connections
data Connection
The Connection newtype is a wrapper that allows us to make connections an instance of the StreamIn/Out classes, without ghc extensions. While this looks sort of like a generic reference to the transport layer it is actually TCP specific, which can be seen in the implementation of the 'Stream Connection' instance.
show/hide Instances
data ConnError
Constructors
ErrorReset
ErrorClosed
ErrorParse String
ErrorMisc String
show/hide Instances
openTCP :: String -> IO Connection
Open a connection to port 80 on a remote host.
isConnectedTo :: Connection -> String -> IO Bool
HTTP
data Request
An HTTP Request. The Show instance of this type is used for message serialisation, which means no body data is output.
Constructors
Request
rqURI :: URImight need changing in future 1) to support * uri in OPTIONS request 2) transparent support for both relative & absolute uris, although this should already work (leave scheme & host parts empty).
rqMethod :: RequestMethod
rqHeaders :: [Header]
rqBody :: String
show/hide Instances
data Response
An HTTP Response. The Show instance of this type is used for message serialisation, which means no body data is output, additionally the output will show an HTTP version of 1.1 instead of the actual version returned by a server.
Constructors
Response
rspCode :: ResponseCode
rspReason :: String
rspHeaders :: [Header]
rspBody :: String
show/hide Instances
data RequestMethod
The HTTP request method, to be used in the Request object. We are missing a few of the stranger methods, but these are not really necessary until we add full TLS.
Constructors
HEAD
PUT
GET
POST
OPTIONS
TRACE
show/hide Instances
simpleHTTP :: Request -> IO (Result Response)
Simple way to get a resource across a non-persistant connection. Headers that may be altered: Host Altered only if no Host header is supplied, HTTP/1.1 requires a Host header. Connection Where no allowance is made for persistant connections the Connection header will be set to close
sendHTTP :: Stream s => s -> Request -> IO (Result Response)
Header Functions
class HasHeaders x
This class allows us to write generic header manipulation functions for both Request and Response data types.
show/hide Instances
data Header
The Header data type pairs header names & values.
Constructors
Header HeaderName String
show/hide Instances
Show Header
data HeaderName

HTTP Header Name type: Why include this at all? I have some reasons 1) prevent spelling errors of header names, 2) remind everyone of what headers are available, 3) might speed up searches for specific headers.

Arguments against: 1) makes customising header names laborious 2) increases code volume.

Constructors
HdrCacheControl
HdrConnection
HdrDate
HdrPragma
HdrTransferEncoding
HdrUpgrade
HdrVia
HdrAccept
HdrAcceptCharset
HdrAcceptEncoding
HdrAcceptLanguage
HdrAuthorization
HdrCookie
HdrExpect
HdrFrom
HdrHost
HdrIfModifiedSince
HdrIfMatch
HdrIfNoneMatch
HdrIfRange
HdrIfUnmodifiedSince
HdrMaxForwards
HdrProxyAuthorization
HdrRange
HdrReferer
HdrUserAgent
HdrAge
HdrLocation
HdrProxyAuthenticate
HdrPublic
HdrRetryAfter
HdrServer
HdrSetCookie
HdrVary
HdrWarning
HdrWWWAuthenticate
HdrAllow
HdrContentBase
HdrContentEncoding
HdrContentLanguage
HdrContentLength
HdrContentLocation
HdrContentMD5
HdrContentRange
HdrContentType
HdrETag
HdrExpires
HdrLastModified
HdrContentTransferEncoding
HdrCustom StringAllows for unrecognised or experimental headers.
show/hide Instances
insertHeader :: HasHeaders a => HeaderName -> String -> a -> a
insertHeaderIfMissing :: HasHeaders a => HeaderName -> String -> a -> a
insertHeaders :: HasHeaders a => [Header] -> a -> a
Inserts multiple headers.
retrieveHeaders :: HasHeaders a => HeaderName -> a -> [Header]
Gets a list of headers with a particular HeaderName.
replaceHeader :: HasHeaders a => HeaderName -> String -> a -> a
URL Encoding
urlEncode :: String -> String
urlDecode :: String -> String
urlEncodeVars :: [(String, String)] -> String
URI authority parsing
data URIAuthority
Constructors
URIAuthority
user :: (Maybe String)
password :: (Maybe String)
host :: String
port :: (Maybe Int)
show/hide Instances
parseURIAuthority :: String -> Maybe URIAuthority

Parse the authority part of a URL.

 RFC 1732, section 3.1:

       //<user>:<password>@<host>:<port>/<url-path>
  Some or all of the parts "<user>:<password>@", ":<password>",
  ":<port>", and "/<url-path>" may be excluded.
Produced by Haddock version 0.7