doc: Set document encoding to UTF-8; typeset my surname correctly.
[bpt/guile.git] / doc / ref / web.texi
index e285c2a..a08cd2c 100644 (file)
@@ -39,6 +39,7 @@ back.
 * HTTP Headers::                How Guile represents specific header values.
 * Requests::                    HTTP requests.
 * Responses::                   HTTP responses.
+* Web Client::                  Accessing web resources over HTTP.
 * Web Server::                  Serving HTTP to the internet.
 * Web Examples::                How to use this thing.
 @end menu
@@ -59,8 +60,8 @@ valid dates.  Error handling for a number of basic cases, like invalid
 dates, occurs on the boundary in which we produce a SRFI 19 date record
 from other types, like strings.
 
-With regards to the web, data types are help in the two broad phases of
-HTTP messages: parsing and generation.
+With regards to the web, data types are helpful in the two broad phases
+of HTTP messages: parsing and generation.
 
 Consider a server, which has to parse a request, and produce a response.
 Guile will parse the request into an HTTP request object
@@ -303,8 +304,8 @@ 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, @pxref{Web Server}.  Otherwise, load the HTTP module, and read
-on.
+pages, @pxref{Web Client}, and @pxref{Web Server}.  Otherwise, load the
+HTTP module, and read on.
 
 @example
 (use-modules (web http))
@@ -339,7 +340,7 @@ For example:
 
 (string->header "FOO")
 @result{} foo
-(header->string 'foo
+(header->string 'foo)
 @result{} "Foo"
 @end example
 
@@ -387,12 +388,6 @@ leaving it as a string.  You could register this header with Guile's
 HTTP stack like this:
 
 @example
-(define (parse-ip str)
-  (inet-aton str)
-(define (validate-ip ip)
-(define (write-ip ip port)
-  (display (inet-ntoa ip) port))
-
 (declare-header! "X-Client-Address"
   (lambda (str)
     (inet-aton str))
@@ -762,7 +757,7 @@ list is itself a list, in the same format as @code{content-type}.
 (parse-header 'accept "text/html,text/plain;charset=utf-8")
 @result{} ((text/html) (text/plain (charset . "utf-8")))
 @end example
-Preference is expressed with qualitiy values:
+Preference is expressed with quality values:
 @example
 (parse-header 'accept "text/html;q=0.8,text/plain;q=0.6")
 @result{} ((text/html (q . 800)) (text/plain (q . 600)))
@@ -852,7 +847,7 @@ indicating any etag, or a list of entity tags.
 Indicates that a response should proceed if and only if the resource has
 been modified since the given date.
 @example
-(parse-header if-modified-since "Tue, 15 Nov 1994 08:12:31 GMT")
+(parse-header 'if-modified-since "Tue, 15 Nov 1994 08:12:31 GMT")
 @result{} #<date ...>
 @end example
 @end deftypevr
@@ -1008,7 +1003,7 @@ A string identifying the server.
 
 @deftypevr {HTTP Header} *|List vary
 A set of request headers that were used in computing this response.
-Used to indicate that server-side content negotation was performed, for
+Used to indicate that server-side content negotiation was performed, for
 example in response to the @code{accept-language} header.  Can also be
 the symbol @code{*}, indicating that all headers were considered.
 @example
@@ -1287,6 +1282,40 @@ Return the given response header, or @var{default} if none was present.
 @end deffn
 
 
+@node Web Client
+@subsection Web Client
+
+@code{(web client)} provides a simple, synchronous HTTP client, built on
+the lower-level HTTP, request, and response modules.
+
+@deffn {Scheme Procedure} open-socket-for-uri uri
+@end deffn
+
+@deffn {Scheme Procedure} http-get uri [#:port=(open-socket-for-uri uri)] [#:version='(1 . 1)] [#:keep-alive?=#f] [#:extra-headers='()] [#:decode-body=#t]
+Connect to the server corresponding to @var{uri} and ask for the
+resource, using the @code{GET} method.  If you already have a port open,
+pass it as @var{port}.  The port will be closed at the end of the
+request unless @var{keep-alive?} is true.  Any extra headers in the
+alist @var{extra-headers} will be added to the request.
+
+If @var{decode-body?} is true, as is the default, the body of the
+response will be decoded to string, if it is a textual content-type.
+Otherwise it will be returned as a bytevector.
+@end deffn
+
+@code{http-get} is useful for making one-off requests to web sites.  If
+you are writing a web spider or some other client that needs to handle a
+number of requests in parallel, it's better to build an event-driven URL
+fetcher, similar in structure to the web server (@pxref{Web Server}).
+
+Another option, good but not as performant, would be to use threads,
+possibly via par-map or futures.
+
+More helper procedures for the other common HTTP verbs would be a good
+addition to this module.  Send your code to
+@email{guile-user@@gnu.org}.
+
+
 @node Web Server
 @subsection Web Server
 
@@ -1331,13 +1360,20 @@ If the read failed, the @code{read} hook may return #f for the client
 socket, request, and body.
 
 @item
-A user-provided handler procedure is called, with the request
-and body as its arguments.  The handler should return two
-values: the response, as a @code{<response>} record from @code{(web
-response)}, and the response body as a string, bytevector, or
-@code{#f} if not present.  We also allow the response to be simply an
-alist of headers, in which case a default response object is
-constructed with those headers.
+A user-provided handler procedure is called, with the request and body
+as its arguments.  The handler should return two values: the response,
+as a @code{<response>} record from @code{(web response)}, and the
+response body as bytevector, or @code{#f} if not present.
+
+The respose and response body are run through @code{sanitize-response},
+documented below.  This allows the handler writer to take some
+convenient shortcuts: for example, instead of a @code{<response>}, the
+handler can simply return an alist of headers, in which case a default
+response object is constructed with those headers.  Instead of a
+bytevector for the body, the handler can return a string, which will be
+serialized into an appropriate encoding; or it can return a procedure,
+which will be called on a port to write out the data.  See the
+@code{sanitize-response} documentation, for more.
 
 @item
 The @code{write} hook is called with three arguments: the client
@@ -1581,7 +1617,7 @@ probably know, we'll want to return a 404 response.
 (define (not-found request)
   (values (build-response #:code 404)
           (string-append "Resource not found: "
-                         (unparse-uri (request-uri request)))))
+                         (uri->string (request-uri request)))))
 
 ;; Now paste this to let the web server keep going:
 ,continue