Next: (www server-utils log), Previous: (www server-utils cookies), Up: The (www *) Modules [Contents][Index]
The (www server-utils answer)
module provides a simple wrapper
around the formatting/accounting requirements of a standard HTTP
response. Additionally, the #:rechunk-content
facility allows
some degree of performance tuning; a server may be able to achieve
better throughput with certain chunk sizes than with others.
The output from compose-response
,
mouthpiece
and string<-headers
is formatted according to their optional style argument.
By default, headers have the form:
NAME ": " VALUE CR LF
Additionally, for compose-response
and
mouthpiece
, the first line, preceding all the
headers, has the form:
"HTTP/" MAJOR "." MINOR SP NNN SP MSG
and a single CRLF
pair separates the headers from the body.
(Actually, mouthpiece hardcodes the protocol version to ‘1.0’,
which is one reason why new code should use compose-response
.)
See (www server-utils modlisp), for another way to format this information.
Keywords: style, protocol-version
Return a command-delegating closure capable of writing a properly
formatted HTTP 1.1 response with Host
header set to host.
The actual status and header format is controlled by style,
an opaque object.
The actual protocol version is controlled by protocol-version,
a pair of integers, such as (1 . 0)
to indicate HTTP 1.0.
The returned closure r accepts commands and args:
#:set-protocol-version pair
Set the major and minor version protocol-version numbers.
#:set-reply-status number message
Set the reply status. message is a short string.
#:add-header name value
name may be #f
, #t
, a string, symbol or keyword.
value is a string. If name is #f
or #t
,
value is taken to be a pre-formatted string, "A: B" or "A:
B\r\n", respectively. If name is not a boolean, value
may also be a tree of strings or a number.
#:add-content [tree …]
tree may be a string, a nested list of strings, or a series of such.
Subsequent calls to #:add-content
append their trees to the
collected content tree thus far.
#:add-formatted format-string [args …]
format-string may be #f
to mean ~S
, #t
to
mean ~A
, or a normal format string. It is used to format
args, and the result passed to #:add-content
.
#:add-direct-writer len write
len is the number of bytes that procedure write will
output to its arg, out-port (passed back), when called during
#:send-reply
. This is to allow sendfile(2) and related
hackery.
#:entity-length
Return the total number of bytes in the content added thus far.
#:rechunk-content chunk
chunk may be #f
, in which case a list of the string
lengths collected thus far is returned; #t
which means to use
the content length as the chunk size (effectively producing one
chunk); or a number specifying the maximum size of a chunk. The
return value is a list of the chunk sizes.
It is an error to use #:rechunk-content
with a non-#f
chunk in the presence of a previous #:add-direct-writer
.
#:inhibit-content! bool
Non-#f
bool arranges for #:send-reply
(below) to
compute content length and add the appropriate header, as usual, but
no content is actually sent. This is useful, e.g., when answering a
HEAD
request. If bool is #f
, #:send-reply
acts normally (i.e., sends both headers and content).
#:send! sock [flags]
Send the properly formatted response to file-port sock. It is
an error to invoke #:send-reply
without having first set
the reply status.
Optional arg flags are the same as for send-request
.
See (www http).
Return a command-delegating closure capable of writing a properly formatted
HTTP 1.0 response to out-port. Optional arg status-box is a
list whose CAR is set to the numeric status code given to a
#:set-reply-status
command. If status-box has length of two
or more, its CADR is set to the content-length on #:send-reply
.
A content-length value of #f
means there have been no calls to
#:add-content
. The commands and their args are:
#:reset-protocol!
Reset internal state, including reply status, headers and content.
This is called automatically by #:send-reply
.
#:set-reply-status number message
Set the reply status. message is a short string.
#:set-reply-status:success
This is equivalent to #:set-reply-status 200 "OK"
.
#:add-header name value
name may be #f
, #t
, a string, symbol or keyword.
value is a string. If name is #f
or #t
,
value is taken to be a pre-formatted string, "A: B" or "A:
B\r\n", respectively. If name is not a boolean, value
may also be a tree of strings or a number.
#:add-content [tree …]
tree may be a string, a nested list of strings, or a series of such.
Subsequent calls to #:add-content
append their trees to the
collected content tree thus far.
#:add-formatted format-string [args …]
format-string may be #f
to mean ~S
, #t
to
mean ~A
, or a normal format string. It is used to format
args, and the result passed to #:add-content
.
#:add-direct-writer len write
len is the number of bytes that procedure write will
output to its arg, out-port (passed back), when called during
#:send-reply
. This is to allow sendfile(2) and related
hackery.
#:content-length
Return the total number of bytes in the content added thus far.
#:rechunk-content chunk
chunk may be #f
, in which case a list of the string
lengths collected thus far is returned; #t
which means to use
the content length as the chunk size (effectively producing one
chunk); or a number specifying the maximum size of a chunk. The
return value is a list of the chunk sizes.
It is an error to use #:rechunk-content
with a non-#f
chunk in the presence of a previous #:add-direct-writer
.
#:inhibit-content! bool
Non-#f
bool arranges for #:send-reply
(below) to
compute content length and add the appropriate header, as usual, but
no content is actually sent. This is useful, e.g., when answering a
HEAD
request. If bool is #f
, #:send-reply
acts normally (i.e., sends both headers and content).
#:send-reply [close]
Send the properly formatted response to out-port, and reset
all internal state (status reset, content discarded, etc). It is
an error to invoke #:send-reply
without having first set
the reply status.
Optional arg close means do a shutdown
on out-port
using close — directly, if an integer, or called with no
arguments, if a thunk — as the shutdown how
argument.
(Note: If out-port is not a socket, this does nothing silently.)
See (guile)Network Sockets and Communication.
If close is specified, the closure forgets about out-port internally; it is an error to call other mouthpiece commands, subsequently.
Here is an example that uses most of the mouthpiece
commands:
(use-modules (www server-utils filesystem) (scripts slurp)) (define SERVER-NAME "Guile-WWW-example-server") (define SERVER-VERSION "1.0") (define STATUS (list #f #f)) (define M (mouthpiece (open-output-file "fake") STATUS)) (define (transmit-file filename) (M #:set-reply-status:success) (M #:add-header 'Server (string-append SERVER-NAME "/" SERVER-VERSION)) (M #:add-header 'Connection "close") (M #:add-header 'Content-Type (filename->content-type filename "text/plain")) (M #:add-content (slurp filename)) (simple-format #t "rechunked: ~A~%" (M #:rechunk-content (* 8 1024))) ;; We don't shutdown because this is a file port; ;; if it were a socket, we might specify 2 to ;; stop both reception and transmission. (M #:send-reply)) (transmit-file "COPYING") -| rechunked: (8192 8192 1605) STATUS ⇒ (200 17989)
For higher performance, you can preformat parts of the response, using
CRLF
, and some lower-level convenience procedures.
If preformatting is not possible (or desirable), you can still
declare a nested list of strings (aka tree) to have a
flat length, i.e., the size in bytes a tree would occupy
once flattened, thus enabling internal optimizations.
(The flat length of a string is its string-length
.)
The string “\r\n”.
Return the flat length of object,
or #f
if not yet computed.
Return a new string made by using format string s on args.
As in simple-format
(which this procedure uses), ~A
expands
as with display
, while ~S
expands as with write
.
Call proc for each recursively-visited leaf in tree, excluding empty lists. It is an error for tree to contain improper lists.
If tree is a string, return its string-length
.
If tree already has a flat-length
, return that.
Otherwise, recursively compute, set, and return the
flat-length
of tree.
Return a new string made from flattening tree.
Set the flat-length
(using tree-flat-length!
)
of tree by side effect.
Return a string made from formatting name/value pairs in alist,
according to the optional style
argument. If unspecified or
specified as #f
, the default is to format headers like so:
NAME #\: #\space VALUE #\cr #\lf
Each name may be a string, symbol or keyword. Each value may be a string, number, symbol, or a tree.
Here is transmit-file
from the above example, slightly modified to use
preformatted headers and fs
:
(define CONSTANT-HEADERS (string<-headers `((#:Server . ,(fs "~A ~A" SERVER-NAME SERVER-VERSION)) (#:Connection . "close")))) (define (transmit-file filename) (M #:set-reply-status:success) (M #:add-header #t CONSTANT-HEADERS) (M #:add-header 'Content-Type (filename->content-type filename "text/plain")) (M #:add-content (slurp filename)) (display (fs "rechunked: ~A~%" (M #:rechunk-content (* 8 1024)))) (M #:send-reply))
Note that mouthpiece
accepts trees for both #:add-header
and
#:add-content
commands. Thus, the following two fragments give the
same result, although the latter is both more elegant and more efficient:
;; Doing things "manually". (walk-tree (lambda (string) (M #:add-content string)) tree) ;; Letting the mouthpiece handle things. (M #:add-content tree)
Next: (www server-utils log), Previous: (www server-utils cookies), Up: The (www *) Modules [Contents][Index]