FastCGI Web Server Interface
This document descripts FastCGI, a feature of REBOL/Command and the REBOL/SDK.
REBOL/Command 2.0 and higher allow REBOL CGI scripts to be called using the FastCGI protocol instead of regular CGI. FastCGI can provide persistence and better performance than regular CGI.
This document describes the differences in the way FastCGI is used with REBOL compared to regular CGI. It assumes that the reader is familiar both with the concept of FastCGI (for more information see www.fastcgi.com) and with the use of regular CGI in REBOL (see the REBOL/Core User's Guide, Network Protocols chapter, CGI - Common Gateway Interface section).
In order to use FastCGI with REBOL, a web server needs to have FastCGI support enabled. Apache modules for FastCGI are available from www.fastcgi.com. FastCGI modules for other web servers are available from commercial vendors.
FastCGI can be used in two different ways with REBOL:
- CGI compatibility mode
This mode is easier to set up and usually does not require any changes to existing CGI scripts. However, this mode does not allow parallel execution of multiple FastCGI requests in the same REBOL process, it only works in Posix environments, and it requires the web server and the FastCGI REBOL process to be on the same machine.
- FastCGI stand-alone mode
This mode requires a slightly different web server configuration and some changes to CGI scripts. It allows multiple requests to be handled by a single REBOL process, works on all platforms, including Posix and Windows, and allows the REBOL process to run on a different machine than the web server.
CGI Compatibility Mode
FastCGI in CGI compatibility mode changes the way the REBOL process is invoked. For regular CGI a separate process is invoked for every CGI request, and each process only handles one single CGI request. For FastCGI in CGI compatibility mode a small number of REBOL processes are spawned (as configured in the web server). These processes remain persistent for some period of time and can handle multiple FastCGI requests during their lifetime, but each can process only one request at a time.
Under FastCGI compatibility mode, scripts are called in the same way and with the same environment as they are in normal CGI, but REBOL automatically detects whether it was invoked using CGI or FastCGI and handles the necessary protocol accordingly.
Scripts invoked using the CGI POST method can read data from system/ports/input. The output of scripts has to be sent to system/ports/output. The CGI or FastCGI environment is available from system/options/cgi, as it is normally.
At the web server FastCGI scripts running in CGI compatibility mode have to be configured as "regular" FastCGI scripts. In Apache this is usually done by associating a certain file extension with FastCGI. For instance to execute all scripts with file names ending in ".fcgi" using FastCGI instead of CGI add the following command to your Apache configuration:
AddHandler fastcgi-script fcgi
Each REBOL FastCGI process created by the web server owns a dynamically created TCP or "local" listening socket through which it receives FastCGI requests and sends the response. REBOL internally translates the FastCGI protocol into the environment usually provided by regular CGI, so regular CGI scripts can be run with FastCGI in CGI compatibility mode without changes.
For a script writer the only difference between FastCGI and CGI is that, since the REBOL process remains persistent, any changes a FastCGI script makes to the REBOL environment remain in effect when the next FastCGI script is executed. For example, if a script defines a word in the global context then that word will remain defined when the next script is executed within the same REBOL process.
Also, CGI scripts should avoid using 'quit to exit, because 'quit will quit the REBOL process, not just end the single request. To just end the current request a script should fall off its end or call 'return or 'exit.
FastCGI Stand-Alone Mode
In this mode your REBOL CGI script is run as a separate process that remains running while CGI requests are redirected to it. In this mode the FastCGI environment has to be set up manually by the script to be executed, and the REBOL process must be started separately, usually during server boot time. The script is not automatically invoked by the web server.
Each script to be run in FastCGI stand-alone mode must be configured on the web server as using an "external server" process. In Apache this is done by adding a configuration command such as:
FastCgiExternalServer /path/to/script -host hostname:portnumber
Here /path/to/script is the virtual script path that is used in the URL for the script. The script (file) itself does not have to exist. Hostname and portnumber point to the host and port on which the REBOL FastCGI server is listening (so, it can be running on a different machine). The hostname can be "localhost" if the web server and the REBOL FastCGI script are on the same machine.
In addition Apache also has to be told to use FastCGI for this class of scripts in the same way as in CGI compatibility mode. The Apache configuration command is:
AddHandler fastcgi-script fcgi
The REBOL process has to be started as a stand-alone process, without the -c option. For example:
/usr/bin/rebol -sqw /my/path/myscript.r
The script executed this way is not regular CGI script. It has to accept FastCGI requests from fastcgi:// ports as shown below:
listen-port: open fastcgi://:12345 forever [ conn-port: first listen-port cgi-data: get-modes conn-port 'cgi ; At this time cgi-data contains the CGI object that is otherwise ; found in system/options/cgi. POSTed data can be read from ; conn-port, the script can handle the request, and the output of ; the script has to be written to conn-port. close conn-port ]
The above example assumes a serialized execution of FastCGI requests. If processing each request takes a considerable amount of time, then it is possible to multiplex FastCGI requests. For example, you could open multiple FastCGI ports, then wait on activity from multiple ports (by using WAIT with a block of port object). Of course, if most of the computation is being done in REBOL, you may need to launch multiple copies of REBOL, then use a central "dispatcher" script to dole out the processing. The advantage of this method over FastCGI compatibility mode is that your first process can serialize requests (to prevent race conditions for certain resources or files).