module Pathinfo:sig
..end
Functions to manipulate PATH_INFO (including SCRIPT_NAME).
These functions attempt to abstract over different modes of invocation. Note that a traditional CGI needs to exist in the file system, while a service running under our embedded HTTP server does not. We want to avoid the case where a CGI would have a PATH_INFO one element longer (due to its filename) than the same service running in HTTP mode, so these functions all work in terms of the concatenation of SCRIPT_NAME and PATH_INFO.
typesubservice =
Netcgi.cgi -> string -> string list -> Nethttp.http_status
The type of sub-service functions: cgi -> argv0 -> argv -> status
val dispatch : ?def:subservice ->
string ->
(string * subservice) list ->
Netcgi.cgi -> Nethttp.http_status
dispatch ?def service map cgi
: dispatcher for services that
implement sub-services based on PATH_INFO. This dispatcher
imposes a standard parameter-passing API based on web
traditions, as a convenience; if you want to use an
idiosyncratic API, e.g.:
http://DOMAIN/foo|bar=baz|zap
then just don't use this function.
It is assumed that your URL-tails all start with the same
top-level service name, whether running as a CGI (in which case
the top-level service name is the name of the executable file
implementing the service) or in Http
mode. This is important
to make sure your service can be switched from one mode to
another and still work identically.
In addition, in order to assure that your application can be
used as a CGI regardless of where that CGI is installed relative
to a DocumentRoot
or ScriptAlias
(to use Apache
terminology), you must define a name for your service. The
dispatch function looks for this service name in your URL, and
then considers the sub-service name and parameters as following.
So the calling API looks like this:
http://DOMAIN/PREFIX/SERVICE/SUBSERVICE[/PARM...][?QUERY_STRING]
where PREFIX
is an arbitrary sequence of /
-separated
components; PREFIX
might be cgi-bin
or ~user/cgi-bin
or
anything else.
You may see the fixed /SERVICE/
component as a liability --
your URLs could be shorter if you leave it out, and you can do
this by not using this convenient dispatcher -- but the cost
will be the inability to run your service transparently in
multiple modes and with arbitrary HTTP-server imposed
ScriptAlias
es.
This whole issue is so annoying that I recommend ignoring PATH_INFO completely, and passing all parameters via QUERY_STRING!
map
is an alist mapping sub-service names to functions
implementing them. The optional def
is a default function,
called if the sub-service name doesn't match any of the names in
map
.
The functions in map
(and def
) are of type subservice
:
each take a CGI activation object, a string which is the
sub-service name under which this function was invoked, and a
list of strings, which are the rest of the PATH_INFO parameters,
and return an HTTP status. So given the map
:
["foo", foofunction]
then the URL
http://DOMAIN/.../SERVICE/foo/bar/baz
will cause foofunction
to be invoked like so:
foofunction cgi "foo" ["bar";"baz"]