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_INET
orPF_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
andAF_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-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, au8
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 symbolchunked
, send the body with “chunked”Transfer-Encoding
. Otherwise, compute and add to the headers its totalContent-Length
.If
flags
contains the symbolclose
, addConnection: 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 addchunked
to 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 (s2s
orig))
, where s2s defaults tostring-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 au8
vector.- 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:
(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 (ifContent-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
orcustom
), 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.,
GET
orPOST
. 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: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).
Return
#t
iff 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
#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 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
isapplication/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-Type
ismultipart/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.