Next: , Previous: URIs, Up: Web


7.3.2 The Hyper-Text Transfer Protocol

The initial motivation for including web functionality in Guile, rather than rely on an external package, was to establish a standard base on which people can share code. To that end, we continue the focus on data types by providing a number of low-level parsers and unparsers for elements of the HTTP protocol.

If you are want to skip the low-level details for now and move on to web pages, see Web Server. Otherwise, load the HTTP module, and read on.

     (use-modules (web http))

The focus of the (web http) module is to parse and unparse standard HTTP headers, representing them to Guile as native data structures. For example, a Date: header will be represented as a SRFI-19 date record (see SRFI-19), rather than as a string.

Guile tries to follow RFCs fairly strictly—the road to perdition being paved with compatibility hacks—though some allowances are made for not-too-divergent texts.

The first bit is to define a registry of parsers, validators, and unparsers, keyed by header name. That is the function of the <header-decl> object.

— Function: make-header-decl sym name multiple? parser validator writer
— Function: header-decl? x
— Function: header-decl-sym decl
— Function: header-decl-name decl
— Function: header-decl-multiple? decl
— Function: header-decl-parser decl
— Function: header-decl-validator decl
— Function: header-decl-writer decl.

A constructor, predicate, and field accessors for the <header-decl> type. The fields are as follows:

sym
The symbol name for this header field, always in lower-case. For example, "Content-Length" has a symbolic name of content-length.
name
The string name of the header, in its preferred capitalization.
multiple?
#t iff this header may appear multiple times in a message.
parser
A procedure which takes a string and returns a parsed value.
validator
A predicate, returning #t iff the value is valid for this header.
writer
A writer, which writes a value to the port given in the second argument.

— Function: declare-header! sym name [#:multiple?] [#:parser] [#:validator] [#:writer]

Make a header declaration, as above, and register it by symbol and by name.

— Function: lookup-header-decl name

Return the header-decl object registered for the given name.

name may be a symbol or a string. Strings are mapped to headers in a case-insensitive fashion.

— Function: valid-header? sym val

Returns a true value iff val is a valid Scheme value for the header with name sym.

Now that we have a generic interface for reading and writing headers, we do just that.

— Function: read-header port

Reads one HTTP header from port. Returns two values: the header name and the parsed Scheme value. May raise an exception if the header was known but the value was invalid.

Returns #f for both values if the end of the message body was reached (i.e., a blank line).

— Function: parse-header name val

Parse val, a string, with the parser for the header named name.

Returns two values, the header name and parsed value. If a parser was found, the header name will be returned as a symbol. If a parser was not found, both the header name and the value are returned as strings.

— Function: write-header name val port

Writes the given header name and value to port. If name is a symbol, looks up a declared header and uses that writer. Otherwise the value is written using display.

— Function: read-headers port

Read an HTTP message from port, returning the headers as an ordered alist.

— Function: write-headers headers port

Write the given header alist to port. Doesn't write the final \r\n, as the user might want to add another header.

The (web http) module also has some utility procedures to read and write request and response lines.

— Function: parse-http-method str [start] [end]

Parse an HTTP method from str. The result is an upper-case symbol, like GET.

— Function: parse-http-version str [start] [end]

Parse an HTTP version from str, returning it as a major-minor pair. For example, HTTP/1.1 parses as the pair of integers, (1 . 1).

— Function: parse-request-uri str [start] [end]

Parse a URI from an HTTP request line. Note that URIs in requests do not have to have a scheme or host name. The result is a URI object.

— Function: read-request-line port

Read the first line of an HTTP request from port, returning three values: the method, the URI, and the version.

— Function: write-request-line method uri version port

Write the first line of an HTTP request to port.

— Function: read-response-line port

Read the first line of an HTTP response from port, returning three values: the HTTP version, the response code, and the "reason phrase".

— Function: write-response-line version code reason-phrase port

Write the first line of an HTTP response to port.