The information in this chapter merely outlines the WASD implementation
details, which are in general very much vanilla CGI and WWW CGI (Common
Gateway Interface) compliant, based the INTERNET-DRAFT authored by D.Robinson
(drtr@ast.cam.ac.uk), 8 January 1996.
CGI Compliant Variables
Environment variables are provided to the script via DCL global symbols.
Each CGI variable symbol name is prefixed with "WWW_" (by default,
although this can be changed using the "/CGI_PREFIX" qualifier, see
5.3 - HTTPd Command Line, this is not recommended if the WASD VMS
scripts are to be used, as they expect CGI variable symbols to be prefixed in
this manner).
Extensions to CGI Variables
In line with other CGI implemenations, additional, non-compliant variables are provided to ease CGI interfacing. These provide the various components of the query string. A keyword query string and a form query string are parsed into separated variables, named
WWW_KEY_number WWW_KEY_COUNT WWW_FORM_form-element-name
plus a number of non-"standard" CGI variables to assist in tailoring
scripts for the WASD environment. Do not make your scripts dependent on any of
these if portability is a goal. See the table below.
CGI Variable Capacity
DCL symbol values are limited to approximately 1024 characters. The CGI
interface will provide symbols with values up to that limit if required. This
should be sufficient for most circumstances.
CGI Variable Descriptions
Remember, all variables are prefixed by "WWW_".
|
The basic CGI symbol names are demonstrated here with a call to a script that simply executes the following DCL code:
$ SHOW SYMBOL WWW_* $ SHOW SYMBOL *Note how the request components are represented for "ISINDEX"-style searching (third item) and a forms-based query (fourth item).
Script output must behave in a CGI-compliant fashion (by way of contrast, see 15.2 - Raw HTTP Output). That is, a CGI script may redirect the location of the document, using a Location: header line, or may supply a data stream beginning with a Content-Type: or Status: header line.
If the script output begins with a CGI-compliant "Content-Type:
text/..." (text document) the HTTPd assumes that output will be
line-oriented and requiring HTTP carriage-control (each record/line terminated
by a line-feed), and will thereafter ensure each record it receives is
correctly terminated before passing it to the client. In this way DCL
procedure output (and the VMS CLI in general) is supported transparently. Any
other content-type is assumed to be binary and no carriage control
is enforced.
Example DCL Scripts
A simple script to provide the system time might be:
$ say = "write sys$output" $! the next two lines make it CGI-compliant $ say "Content-Type: text/plain" $ say "" $! start of plain-text script output $ show time
A script to provide the system time more elaborately (using HTML):
$ say = "write sys$output" $! the next two lines make it CGI-compliant $ say "Content-Type: text/html" $ say "" $! start of HTML script output $ say "<HTML>" $ say "Hello ''WWW_REMOTE_HOST'" !(CGI variable) $ say "<P>" $ say "System time on node ''f$getsyi("nodename")' is:" $ say "<H1>''f$cvtime()'</H1>" $ say "</HTML>"
A script does not have to output a CGI-compliant data stream. If it begins with a HTTP header status line (e.g. "HTTP/1.0 200 Success"), HTTPd assumes it will supply a raw HTTP data stream, containing all the HTTP requirements. This is the equivalent of the no-parse-header, or "nph..." named scripts of some environments.
Any such script must observe the HyperText Transfer Protocol, supplying a
full header and body with correct carriage-control.
Raw HTTP DCL Script
The following example show a DCL script. Note the full HTTP header and each line explicitly terminated with a carriage-return and line-feed pair.
$ lf[0,8] = %x0a $ say = "write sys$output" $! the next line determines that it is raw HTTP stream $ say "HTTP/1.0 200 Success" + lf $ say "Content-Type: text/html" + lf $! response header separating blank line $ say lf $! start of HTML script output $ say "<HTML>" $ say "Hello ''WWW_REMOTE_HOST'" $ say "<P>" $ say "Local time is ''WWW_REQUEST_TIME_LOCAL'" $ say "</HTML>"
To assist with the generation of HTTP responses, including the transfer of
binary content from files (copying a file back to the client as part of the
request), and the processing of the contents of POSTed requests from DCL
the
HT_ROOT:[SRC.MISC]CGIUTL.C
is available. Also see DCL Processing of POSTed Content in this chapter.
Raw HTTP C Script
When scripting using the C programming language there can be considerable efficiencies to be gained by providing a binary output stream from the script. This may be simply provided using a code construct similar to following to reopen <stdout> in binary mode.
/* reopen output stream so that the '\r' and '\n' are not filtered */ #ifdef __DECC if ((stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")) == NULL) exit (vaxc$errno); #endif
This is used consistently in WASD scripts. Carriage control must be supplied as part of the C standard output (no differently to any other C program). Output can be be explicitly fflush()ed at any stage to overtly send output buffered by the C RTL to the client. If the fwrite() library function is used then to maintain the buffering efficiency an additional reopen() parameter is required following the "ctx=bin", "ctx=xplct".
The full HTTP header can be supplied (as in the following example) or just a CGI-compliant header output.
fprintf (stdout, "HTTP/1.0 200 Success\r\n\ Content-Type: text/html\r\n\ \r\n\ <HTML>\n\ Hello %s\n\ <P>\n\ System time is %s\n\ </HTML>\n", getenv("WWW_REMOTE_HOST"), getenv("WWW_REQUEST_TIME_LOCAL"));
For POST and PUT HTTP methods (e.g. a POSTed HTML form) the body of the request may be read from the HTTP$INPUT stream. For executable image scripts requiring the body to be present on SYS$INPUT (the C language <stdin> stream) a user-mode logical may be defined immediately before invoking the image, as in the example.
$ EGSCRIPT = "$HT_EXE:EGSCRIPT.EXE" $ DEFINE /USER SYS$INPUT HTTP$INPUT $ EGSCRIPT
The HTTP$INPUT stream may be explicitly opened and read. Note that this is a raw stream, and HTTP lines (carriage-return/line-feed terminated sequences of characters) may have be blocked together for network transport. These would need to be explicity parsed by the program.
NOTE:
Versions of the server prior to 4.3 supplied the full request (header then
body) to the script. This was not fully CGI-compliant. Versions 4.3 and
following supply only the body, although the previous behaviour may be
explicitly selected using the configuration parameter [DclFullRequest].
DCL Processing of POSTed Content
To assist with the processing of the contents of POSTed requests from DCL
the
HT_ROOT:[SRC.MISC]CGIUTL.C
is available. This utility reads the request body, decoding form-URL-encoded
contents into DCL symbols and/or a scratch file, allowing a DCL procedure to
easily and effectively process this form of request. An example form,
HT_ROOT:[SRC.MISC]CGIUTL_EXAMPLE.HTML,
and example script,
HT_ROOT:[SCRIPT]CGIUTL_EXAMPLE.COM,
shows how this utility may be deployed. This utility also has functionality
for generating HTTP responses.
15.4 - CGI Function Library
A source code collection of C language functions useful for processing the more vexing aspects of CGI programming is available in
HT_ROOT:[SRC.MISC]CGILIB.C
Functionality includes
The WASD scripts use this library extensively and may serve as example applications.