(www http) module includes module-configuration fluids,
procedures for high-level HTTP
operation, low-level HTTP message object access, and common messages.
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
Return a TCP stream socket connected to the location specified by
protocol proto, addrfam and address. proto
PF_UNIX, and the other args take
(AF_INET ipaddr portno), where ipaddr is
an integer. Use
(car (hostent:addr-list (gethost host)))
to compute the ipaddr of host (a string).
(AF_UNIX filename), made, for example, by
(list AF_UNIX "/tmp/foo-control").
AF_foo are names of variables
that have constant values, not symbols.
Return an HTTP connection (a socket) to host (a string) on TCP port port (default 80 if unspecified).
Keywords: headers, body, flags, protocol-version
Submit to socket sock an HTTP request using method
(a symbol) and url, an object returned by
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):
This is called if the transfer is not “chunked” (see below). m returns the total length (in bytes) of the data.
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
m should return
(values #f #f).
flags contains the symbol
chunked, send the body
Transfer-Encoding. Otherwise, compute and
add to the headers its total
flags contains the symbol
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
Keywords: s2s, intervene, flags
Receive the pending (from
Return an HTTP message object. The header names are symbols made
(string->symbol (s2s orig)), where s2s
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.
hget is a procedure that takes one arg sel.
Return the headers (alist).
Return the name normalization procedure (involving s2s, described above).
Normalize it; return the associated header value.
Return the associated header value.
#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!).
u8, the body is a
custom, the following item in flags should be a thunk that returns four values (all procedures) that support the chunk transfer protocol. These are:
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.
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”
or read in one swoop (if
Content-Length is given),
or from multiple inexact chunks (the default).
no-cat, then all multi-chunk transfers are not “concatenated”; instead, the message body is the list of chunk data (string,
custom), in order of reception.
Here is an example that uses
intervene to arrange for the message body to be a
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
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
(i.e., a string name).
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.,
POST. It may also be a string.
url is a url object returned by
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’;
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).
Return the HTTP version in use in HTTP message msg.
Return the status code returned in HTTP message msg.
Return the text of the status line from HTTP message msg.
#t iff status code of msg
indicates a successful request.
#t iff status (string or integer) is
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.
Return a list of the headers from HTTP message msg.
Return the header field named header from HTTP message msg,
#f if no such header is present in the message.
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
(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
and furthermore all the fkey and fvalue are transformed
url-coding:encode (see url-coding) with the additional
#\& (ampersand) and
#\= (equal sign).
with each field in fields formatted as a MIME sub-part.