module Netcgi_common:sig
..end
Functions to develop new connectors.
The following module is provided as a set of helper functions to
define new connectors. As a normal user of Netcgi
, you should
not use this module.
The goal of this module is to factor out common routines to easily set up new connectors. Here is the normal flow of operations:
Netcgi_common.update_props_inheader
helps you to sort them and
to normalize the input header fields. You also need to set up a
Netchannels.out_obj_channel
to the output stream of your
connector. Then, Netcgi_common.cgi_environment
can create an
environment object for you. If stderr
output is not appropriate
(e.g. ot is not redirected to the server log), you need to
override #log_error
.Netcgi_common.cgi
creates a CGI object. Often, arguments are read from the
environment #cgi_query_string
(in case of GET) or from an input
channel (in case of POST). Netcgi_common.cgi_with_args
handles
this for you: it requires a Netchannels.in_obj_channel
from
which the arguments are read (only used in the case of POST).Netcgi_common.exn_handler_default
provides a default error
page for uncaught exceptions. It also allows the user to pass his
own exception handler that has precedence on the default one.To see this schema in use, we recommend you have a look to the implementation of the CGI connector because it is very simple.
typerepresentation =
[ `MIME of Netmime.mime_message | `Simple of Netmime.mime_body ]
typestore =
[ `File of string | `Memory ]
exception Oversized
exception Too_many_arguments
Hit the limit max_arguments
class type cgi_argument =object
..end
See Netcgi.cgi_argument
.
class type rw_cgi_argument =object
..end
class simple_arg :?ro:bool -> string -> string ->
rw_cgi_argument
class mime_arg :?work_around_backslash_bug:bool -> ?name:string -> Netmime.mime_message ->
rw_cgi_argument
See Netcgi.Argument.mime
.
The cookie implementation has been moved to Nethttp.Cookie
.
New code should directly call the functions defined there.
module Cookie:sig
..end
type
config = {
|
tmp_directory : |
|
tmp_prefix : |
|
permitted_http_methods : |
|
permitted_input_content_types : |
|
input_content_length_limit : |
|
max_arguments : |
|
workarounds : |
|
default_exn_handler : |
See Netcgi.config
.
typeoutput_type =
[ `Direct of string
| `Transactional of
config ->
Netchannels.out_obj_channel -> Netchannels.trans_out_obj_channel ]
See Netcgi.output_type
.
val fix_MSIE_Content_type_bug : string -> string
fix_MSIE_Content_type_bug ct
transforms the content-type
string ct
to fix the MSIE Content-Type bug.
val is_MSIE : string -> bool
is_MSIE user_agent
tells whether the user_agent
is Microsoft
Internet Explorer. Useful to know when to apply
Netcgi_common.fix_MSIE_Content_type_bug
.
class cgi_environment :config:config -> properties:(string * string) list -> input_header:(string * string) list -> Netchannels.out_obj_channel ->
object
..end
new cgi_environment ~config ~properties ~input_header out_obj
generates a Netcgi.cgi_environment
object, from the arguments.
typeother_url_spec =
[ `Env | `None | `This of string ]
typequery_string_spec =
[ `Args of rw_cgi_argument list
| `Env
| `None
| `This of cgi_argument list ]
typecache_control =
[ `Max_age of int | `No_cache | `Unspecified ]
See Netcgi.cache_control
.
typerequest_method =
[ `DELETE | `GET | `HEAD | `POST | `PUT of cgi_argument ]
val string_of_request_method : request_method -> string
typearg_store_type =
[ `Automatic
| `Automatic_max of float
| `Discard
| `File
| `File_max of float
| `Memory
| `Memory_max of float ]
typearg_store =
cgi_environment ->
string -> Netmime.mime_header_ro -> arg_store_type
See Netcgi.arg_store
.
class cgi :cgi_environment -> output_type -> request_method -> cgi_argument list ->
object
..end
cgi env op meth args
constructs Netcgi.cgi
objects.
val cgi_with_args : (cgi_environment ->
output_type ->
request_method -> cgi_argument list -> 'a) ->
cgi_environment ->
output_type ->
Netchannels.in_obj_channel -> arg_store -> 'a
cgi_with_args (new cgi) env out op ?put_arg in_chan
constructs
a Netcgi.cgi
object. However, new cgi
can be replaced by
any function, so it is easy to use this to construct extensions
of the cgi
class (as needed by some connectors). The
arguments of the cgi object are taken from the environment env
(for HEAD, GET, DELETE) or from the in_chan
(for POST, PUT)
and processed according to arg_store
.
HTTP
if the data does not conform the standards or it not
allowed.exception HTTP of Nethttp.http_status * string
Exception raised by various functions of this library to return to the user agent an appropriate error page with the specified http-status (this exception must be caught by the connector and a default answer sent).
The string is a description of the cause of the error.
This exception is for use by connectors only, users should deal
with the exceptions in their code by generating a response with
the usual #set_header
and #out_channel
of Netcgi.cgi
.
val exn_handler_default : cgi_environment ->
exn_handler:(cgi_environment -> (unit -> unit) -> unit) ->
finally:(unit -> unit) -> (unit -> exn option) -> unit
exn_handler_default env ~exn_handler ~finally run_cgi
will
basically execute exn_handler env run_cgi
. Provided that the
environment config default_exn_handler
is set to true
(the
default), any exception e
not caught by the user provided
exn_handler
(or that is raised by it) will be passed to the
default handler of OCamlNet which will rollback the current
output, produce a page describing the exception e
, and close
the output channel of env
. Note that the default handler
treats HTTP
exceptions specially -- for example, the response
to HTTP(`Method_not_allowed,...)
includes an "Allow" header
(as mandated by HTTP/1.1);...
Note that, regardless of the value of default_exn_handler
, the
Exit
exception is always caught and treated like an
acceptable early termination (thus produces no error page).
Whether run_cgi
terminates normally or by an exception,
finally()
is executed last.
Sometimes, you want that some "special" exceptions (for example
exceptions internal to the connector) CANNOT to be caught by
exn_handler
. In this case, run_cgi()
catches the exception,
say e
, and returns it as Some e
. The exception e
will "go
through" exn_handler_default
, it will not even be passed to
the default handler. Therefore, you must take care that it is
handled by the surrounding code or your connector may die
without an error message. Of course, run_cgi
must return
None
if no "special" exception is raised.
REMARK: Stricly speaking, exn_handler env run_cgi
is obviously
not possible because the return type of run_cgi
is not unit
but you can ignore that to understand what this function does.
val error_page : cgi_environment ->
Nethttp.http_status ->
(string * string list) list -> string -> string -> unit
error_page env status fields msg detail
: Logs an error message and
outputs an error page via env
.
status
is the status of the error page, e.g. `Internal_server_error
.
fields
are put into the response header of the error page.
msg
occurs in the log message and in the error page, and should
be a concise description without linefeeds. detail
is only
printed to the error page, and may be longer than this, and may
also include HTML markup.
The following functions are used in several connectors and are gouped here for convenience.
val update_props_inheader : string * string ->
(string * string) list * (string * string) list ->
(string * string) list * (string * string) list
update_props_inheader (name, value) (props, inheader)
returns
(props, inheader)
to which the new parameter name
-value
has been added -- to props
or inheader
, depending on name
.
Unless you know what you are going, you must use this
function to classify parameters as it also performs some
standardisation.
val rm_htspace : (char -> bool) -> string -> int -> int -> string
rm_htspace is_space s low up
returns the substring s.[low
.. up - 1]
stripped of possible heading and trailing spaces
identified by the function is_space
.
Invalid_argument
if low < 0
or up > String.length s
val rev_split : (char -> bool) -> string -> string list
split_rev is_delim s
split s
at each character is_delim
and returns the list of substrings in reverse order. Several
consecutive delimiters are treated as a single one. The
substrings do not share s
memory.
val is_prefix : string -> string -> bool
is_prefix pre s
checks whether pre
is a prefix of s
.
typehttp_method =
[ `DELETE | `GET | `HEAD | `POST | `PUT ]
val string_of_http_method : http_method -> string
Returns the string value of the method