Module Restful.Pathinfo

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.


type subservice = 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 ScriptAliases.

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"]