Netcgi_porting



Porting cgi programs to netcgi

The library netcgi is a revised version of the old cgi library. As any software, cgi aged, and suffered more and more from inadequate interfaces. Because of this it became necessary to improve the interfaces from grounds up. The result is netcgi, a new major version that tries to continue the good parts of cgi while replacing its problematic edges.

When this text is written, netcgi is still being developed, and subject of discussion.

Why porting?

It is not possible to use cgi and netcgi at the same time in the same application. This means that one cannot gradually upgrade from cgi to netcgi by using more and more of the netcgi features. Instead of this, it is necessary to switch from cgi to netcgi at one point in the lifetime of the web application.

The main benefit is that you have access to the newest netcgi features. There are already a number of connectors that are not present in cgi. Furthermore, new features will only be added to netcgi. Because the Nethttpd library also uses netcgi in Ocamlnet 2, you must switch if you link Nethttpd to your program.

However, if your application is already at or near its end of lifetime, there is no need to port it to netcgi. The cgi library will remain in Ocamlnet 2, and bugs will be fixed.

Module Organization

The new organization is very simple:

There is also a module Netcgi_compat trying to ease porting. See below for a discussion.

Interface Changes

Most of the types remain the same, or almost the same. A few changes have been done:

The connectors, however, are now created in very different ways. This is mainly driven by uniformity: There should be a method of creating web connectors that works for every kind of connector. Because of this, the code instantiating connectors in application must always be changed so it matches the new, uniform conventions. Fortunately, this code is usually not very extensive.

Porting strategies

Strategy: Use new API

In the long term this is the best strategy. In principle, one has to distinguish between

Porting the first parts is fairly simple, because the types of the netcgi values do not change much. For example, the function web_page for cgi

 
(* This is [cgi] code! *)
let web_page (cgi : Netcgi_types.cgi_activation) =
  let webarg = cgi # argument_value "webarg" in
  cgi # set_header();
  cgi # output # output_string ("The argument is: " ^ webarg)

would read in the version for netcgi as follows:

 
(* This is [netcgi] code! *)
let web_page (cgi : Netcgi.cgi_activation) =
  let webarg = cgi # argument_value "webarg" in
  cgi # set_header();
  cgi # output # output_string ("The argument is: " ^ webarg)

The only change is that the type cgi_activation is now defined in the module Netcgi and no longer in Netcgi_types. It is expected that this simple way of porting applies to almost all parts of netcgi applications.

By the way, the type cgi_activation can now be abbreviated as cgi, as this is the type name that needs to be written down most frequently.

The new CGI connector

In cgi, the CGI connector is selected by instantiating the class Netcgi.std_activation, as in:

(* This is [cgi] code! *)
let cgi = new Netcgi.std_activation() in 
process cgi

It is assumed that process is a function taking a cgi_activation as argument, and processing the request.

The corresponding netcgi call is:

(* This is [netcgi] code! *)
Netcgi_cgi.run process

As you see, Netcgi_cgi.run is now responsible for calling process.

The new FastCGI connector

In cgi there are several ways of using FastCGI. The most common is to call Netcgi_fcgi.serv as in:

(* This is [cgi] code! *)
Netcgi_fcgi.serv process optype

It is assumed that process is a function taking a cgi_activation as argument, and processing the request. optype is a valid operating type.

The corresponding netcgi call is:

(* This is [netcgi] code! *)
let process' cgi = process (cgi :> Netcgi.cgi_activation) in
Netcgi_fcgi.run ~output_type:optype process'

Note that the argument of process' is a slightly extended version of cgi_activation, so you usually need the coercion to cut off the additional part of the object interface.

The new AJP connector

TO BE WRITTEN

Strategy: Use Netcgi_compat

TO BE WRITTEN

Strategy: Postpone porting effort

TO BE WRITTEN

Disadvantages: