The (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:head ; via http:request http:get ; likewise http:post-form ; likewise
Return a TCP stream socket connected to the location specified by protocol proto, addrfam and address. proto is
PF_INETorPF_UNIX, and the other args take corresponding forms:
PF_INET(AF_INETipaddr portno), where ipaddr is an integer. Use(car (hostent:addr-list (gethosthost)))to compute the ipaddr of host (a string).PF_UNIX(AF_UNIXfilename), made, for example, by
(list AF_UNIX "/tmp/foo-control").Note that
PF_fooandAF_fooare 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-versionSubmit 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 CRLFand body, which may be
#f(which means no body), a string or list of them, au8vector 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
flagscontains the symbolchunked, send the body with “chunked”Transfer-Encoding. Otherwise, compute and add to the headers its totalContent-Length.If
flagscontains the symbolclose, addConnection: closeto 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 addchunkedto flags as well as the headers:TE: trailers Connection: TEReturn an unspecified object pending that can be passed to
receive-response.
Keywords: s2s, intervene, flagsReceive the pending (from
send-request) response. Return an HTTP message object. The header names are symbols made by(string->symbol (s2sorig)), where s2s defaults tostring-titlecase. The status code is a 3-digit integer. The body of the message may be#fif 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
#fvalue 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 au8vector.- If flags contains the symbol
custom, the following item in flags should be four values (all procedures) that support the chunk transfer protocol. These are:
(mkxlen)- 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-rlist)- Return a new container formed by reversing list and concatenating its elements.
(subseqx 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 (ifContent-Lengthis 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,u8orcustom), 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).
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 compatability): 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.,
GETorPOST. It may also be a string. url is a url object returned byurl: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:requesthandles 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-Lengthheader is computed to have value 33 (the sum of 13, 8 and 12).
Return
#tiff status code of msg indicates a successful request.
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 the header field named header from HTTP message msg, or
#fif no such header is present in the message.
Submit an http request using the
POSTmethod 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
#fto mean "text/plain". transfer-encoding is one of the tokens specified by RFC 1521, or#fto 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-Typeisapplication/x-www-form-urlencoded, and furthermore all the fkey and fvalue are transformed byurl-coding:encode(see url-coding) with the additional reserved characters#\&(ampersand) and#\=(equal sign).Otherwise, the
Content-Typeismultipart/form-data, with each field in fields formatted as a MIME sub-part.
NB: The following two procedures will NO LONGER BE AVAILABLE
after 2013-02-28. Using send-request and receive-reply
directly is more flexible and featureful.