Next: , Previous: , Up: The (www *) Modules   [Contents][Index]


1 (www http)

The (www http) module includes module-configuration fluids, procedures for high-level HTTP operation, low-level HTTP message object access, and common messages.

1.1 Dynamic Configuration

Fluid: protocol-version

A pair of integers representing the major and minor portions of the protocol version this module should support. The default value is (1 . 0). Users:

http:request
http:post-form   ; via http:request

1.2 High-Level HTTP Operation

Procedure: http:connect proto addrfam address [address-rest…]

Return a TCP stream socket connected to the location specified by protocol proto, addrfam and address. proto is PF_INET or PF_UNIX, and the other args take corresponding forms:

PF_INET

(AF_INET ipaddr portno), where ipaddr is an integer. Use (car (hostent:addr-list (gethost host))) to compute the ipaddr of host (a string).

PF_UNIX

(AF_UNIX filename), made, for example, by
(list AF_UNIX "/tmp/foo-control").

Note that PF_foo and AF_foo are names of variables that have constant values, not symbols.

Procedure: http:open host [port]

Return an HTTP connection (a socket) to host (a string) on TCP port port (default 80 if unspecified).

Procedure: send-request sock method url [keyword value…]
Keywords: headers, body, flags, protocol-version 

Submit to socket sock an HTTP request using method (a symbol) and url, an object returned by url:parse, forming the message with additional headers, a list of strings, each of which should have one of the forms:

NAME ": " VALUE
NAME ": " VALUE CRLF

and body, which may be #f (which means no body), a string or list of them, a u8 vector or list of them, or a procedure m which manages the transmission of the body data by supporting the body transmission protocol. This means m takes one arg, command (symbol):

content-length

This is called if the transfer is not “chunked” (see below). m returns the total length (in bytes) of the data.

next-chunk

Return two values: the length (in bytes) of the next chunk of data to send, and either a string, or a procedure w that does the actual writing to its port arg (which will be sock). If there is no more data, both values should be #f, i.e., m should return (values #f #f).

If flags contains the symbol chunked, send the body with “chunked” Transfer-Encoding. Otherwise, compute and add to the headers its total Content-Length.

If flags contains the symbol close, add Connection: close to the headers.

The protocol-version is a pair specifying the major and minor version numbers of HTTP to send as. It defaults to (1 . 1). For HTTP 1.x (x >= 1), automatically add chunked to flags as well as the headers:

TE: trailers
Connection: TE

Return an unspecified object pending that can be passed to receive-response.

Procedure: receive-response pending [keyword value…]
Keywords: s2s, intervene, flags 

Receive the pending (from send-request) response. Return an HTTP message object. The header names are symbols made by (string->symbol (s2s orig)), where s2s defaults to string-titlecase. The status code is a 3-digit integer. The body of the message may be #f if there is no body possible (per HTTP). Otherwise, its value depends on intervene and flags.

  • If intervene is specified, it should be a procedure that takes two args, hget and flags and returns two values, new-headers and new-flags. It is called after the headers are parsed but before the body is received so that its returned values may influence the body processing.

    hget is a procedure that takes one arg sel.

    #f

    Return the headers (alist).

    #t

    Return the name normalization procedure (involving s2s, described above).

    string

    Normalize it; return the associated header value.

    symbol

    Return the associated header value.

    A #f value for new-headers means “don’t change the headers”. Likewise, for new-flags. Otherwise, the respective items are replaced (NB: not just added!).

  • If flags is null (the default), the body is a string.
  • If flags contains the symbol u8, the body is a u8 vector.
  • If flags contains the symbol custom, the following item in flags should be a thunk that returns four values (all procedures) that support the chunk transfer protocol. These are:
    (mkx len)

    Create and return a container capable of holding len bytes.

    (r! x sock)

    Fill x, reading from sock. Return the number of bytes read (positive integer), or zero on EOF.

    (cat-r list)

    Return a new container formed by reversing list and concatenating its elements.

    (subseq x len)

    Return a new container that holds the first len bytes of container x.

    The message body is a single container, either constructed from multiple exact chunks (“chunked” Transfer-Encoding), or read in one swoop (if Content-Length is given), or from multiple inexact chunks (the default).

  • If flags contains the symbol no-cat, then all multi-chunk transfers are not “concatenated”; instead, the message body is the list of chunk data (string, u8 or custom), in order of reception.

Here is an example that uses receive-response argument intervene to arrange for the message body to be a u8 vector if the Content-Type is not “text/*”.

(use-modules
 (srfi srfi-13)   ; string-prefix?
 (www url))       ; url:parse

(define (text? type)
  (string-prefix? "text/" type))

(define (u8-maybe hget flags)
  (cond ((hget 'Content-Type)
         => (lambda (type)
              (values #f (and (not (text? type))
                              (cons 'u8 flags)))))
        (else
         (values #f #f))))

(define SOCK (http:open …))

(define (gimme string)
  (send-request SOCK 'GET (url:parse string)))

(define (ok pending)
  (receive-response pending #:intervene u8-maybe))

(define ICO (ok (gimme "http://localhost/favicon.ico")))
(define IDX (ok (gimme "http://localhost/index.html")))

(http:message-body ICO)
⇒ #u8(0 0 1 0 1 0 46 …)

(http:message-body IDX)
⇒ "<?xml version=\"1.0\" …"

Note that to find the content type in u8-maybe, we rely on the default header-name normalization of string-titlecase, since we know ok does not specify #:s2s s2s in its call to receive-response. To enable u8-maybe to work with any pending response, you can instead use (hget "Content-Type") (i.e., a string name).

Procedure: http:request method url [headers [body]]

Submit an HTTP request using method and url, wait for a response, and return the response as an HTTP message object. The field types and values of this message object are as described in receive-response, with two exceptions (for backward compatibility): the status code is a string; the header names are symbols, all lower-case.

method is the symbolic name of some HTTP method, e.g., GET or POST. It may also be a string. url is a url object returned by url:parse. Optional args headers and body are lists of strings that comprise the lines of an HTTP message. The header strings should not end with ‘CR’ or ‘LF’ or ‘CRLF’; http:request handles that. Also, the Content-Length header and Host header are calculated automatically and should not be supplied. Here are two examples:

(http:request 'GET parsed-url
  (list "User-Agent: Anonymous/0.1"
        "Content-Type: text/plain"))

(http:request 'POST parsed-url
  (list "User-Agent: Fred/0.1"
        "Content-Type: application/x-www-form-urlencoded")
  (list "search=Gosper"
        "&case=no"
        "&max_hits=50"))

In the second example, the Content-Length header is computed to have value 33 (the sum of 13, 8 and 12).

1.3 Low-Level HTTP Message Object Access

Procedure: http:message-version msg

Return the HTTP version in use in HTTP message msg.

Procedure: http:message-status-code msg

Return the status code returned in HTTP message msg.

Procedure: http:message-status-text msg

Return the text of the status line from HTTP message msg.

Procedure: http:message-status-ok? msg

Return #t iff status code of msg indicates a successful request.

Procedure: http:status-ok? status

Return #t iff status (string or integer) is 2xx.

Procedure: http:message-body msg

Return the body of the HTTP message msg.

An HTTP message header is represented by a pair. The CAR is a symbol representing the header name, and the CDR is a string containing the header text. E.g.:

'((date . "Thu, 29 May 1997 23:48:27 GMT")
  (server . "NCSA/1.5.1")
  (last-modified . "Tue, 06 May 1997 18:32:03 GMT")
  (content-type . "text/html")
  (content-length . "8097"))

Note: these symbols are all lowercase, although the original headers may be mixed-case. Clients using this library should keep this in mind, since Guile symbols are case-sensitive.

Procedure: http:message-headers msg

Return a list of the headers from HTTP message msg.

Procedure: http:message-header header msg

Return the header field named header from HTTP message msg, or #f if no such header is present in the message.

1.4 Common Messages

Procedure: http:post-form url extra-headers fields

Submit an http request using the POST method on the url. extra-headers is a list of extra headers, each a string of form "name: value …".

The "Content-Type" and "Host" headers are sent automatically and do not need to be specified. fields is a list of elements of the form (fkey . fvalue), where fkey is a symbol and fvalue is normally a string.

fvalue can also be a list of file-upload specifications, each of which has the form (source name mime-type transfer-encoding). source can be a string or a thunk that returns a string.

The rest of the elements are strings or symbols: name is the filename (only the non-directory part is used); mime-type is a type/subtype pair such as "image/jpeg", or #f to mean "text/plain". transfer-encoding is one of the tokens specified by RFC 1521, or #f to mean "binary". File-upload spec elements with invalid types result in a "bad upload spec" error prior to the http request.

Note that source is used directly without further processing; it is the caller’s responsibility to ensure that the MIME type and transfer encoding specified describe source accurately.

If there are no file-upload specifications in fields, the Content-Type is application/x-www-form-urlencoded, and furthermore all the fkey and fvalue are transformed by url-coding:encode (see (www url-coding)) with the additional reserved characters #\& (ampersand) and #\= (equal sign).

Otherwise, the Content-Type is multipart/form-data, with each field in fields formatted as a MIME sub-part.


Next: (www url), Previous: The (www *) Modules, Up: The (www *) Modules   [Contents][Index]