FastCGI is an enhancement to the existing CGI (Common Gateway Interface), which is a standard for interfacing external applications with Web Servers. Like CGI, FastCGI applications run in separate, isolated processes. Some of the advantages of using FastCGI are as follows:
Enables applications to persist between client requests, eliminates application start up overhead, and allows the application to maintain state between client calls.
Enables applications to reside on remote systems (a different system from where the Web Server is running).
Enables additional flexibility in application functionality, with explicit support for applications that do client authentication and filtering of input.
Allows the administrator to restrict the impact on the system that is caused by the FastCGI servers.
FastCGI plug-in allows Web Server to safely work with popular third-party dynamic content generation technologies (such as Perl and Python) in a scalable way.
For more information on FastCGI, refer to the specification at http://www.fastcgi.com/devkit/doc/fcgi-spec.html.
FastCGI plug-in provides the following Server Application Functions (SAFs):
The various parameters and "error-reason" strings for the FastCGI SAFs are described in the following sections:
auth-fastcgi is a PatchCheck function. This function is used to forward the request to an “Authorizer” FastCGI application. On successful authorization, a return code of 200 is sent. Otherwise, the response from the “Authorizer” FastCGI application is sent back to the user agent.
More information on the FastCGI Roles can be found here http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6.
The parameters accepted by auth-fastcgi SAF, are available at: FastCGI SAF Parameters.
The following obj.conf code example demonstrates the use of auth-fastcgi:
PathCheck fn="auth-fastcgi" app-path="/usr/bin/perl" app-args="/fastcgi/apps/auth/SimpleAuth.pl" bind-path="localhost:3432".
The responder-fastcgi is a Service function. This function is used to forward the request to a FastCGI application that acts as a “Responder”. The response from the Responder application is sent back to the user agent. More information on the FastCGI Roles can be found at http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6.
The list of parameters accepted by responder-fastcgi SAF, are available at:FastCGI SAF Parameters .
The following obj.conf code example demonstrates the use of responder-fastcgi:
Service fn="responder-fastcgi" app-path="/fastcgi-enabled-php-installation/bin/php" bind-path="localhost:3433" app-env="PHP_FCGI_CHILDREN=8" app-env="PHP_FCGI_MAX_REQUEST=500".
The filter-fastcgi is a Service function. This function is used to forward the request to a “Filter” type of FastCGI application. The “Filter” application receives the information associated with the HTTP request and also the data from the file stored on the server. The “Filter” application then generates a “filtered” version of the data stream as the response. This is sent back to the user agent. More information on the FastCGI Roles can be found at http://www.fastcgi.com/devkit/doc/fcgi-spec.html#S6.
The list of parameters accepted by filter-fastcgi SAF, are available at:FastCGI SAF Parameters .
The following obj.conf code example demonstrates the use of filter-fastcgi:
Service fn="filter-fastcgi" app-path="/fastcgi/apps/filter/SimpleFilter" bind-path="localhost:3434" app-env="LD_LIBRARY_PATH=/fastcgi/fcgi-2.4/libfcgi/.libs" min-procs=2
The error-fastcgi is an Error function. The error-fastcgi SAF handles the errors specific to the FastCGI plug-in. This function however does not handle the HTTP errors. On error, FastCGI plug-in can be configured to display a specific page or redirect the request to a specific URL.
The list of parameters accepted by error-fastcgi SAF, are available at: FastCGI SAF Parameters.
The following obj.conf snippet demonstrates the use of error-fastcgi:
Error fn="error-fastcgi" error-reason="Invalid Parameters" error-url="http://www.foo.com/errorPage.html"
See FastCGI SAF Parameters for information on the error-fastcgi parameters.
The FastCGI plug-in SAFs, "auth-fastcgi“ , “responder-fastcgi” and “filter-fastcgi”, all accept the following parameters unless otherwise mentioned explicitly:
Note that parameters chroot, user, group and nice are applicable to only UNIX platforms. On Windows platforms, these parameters are ignored.
app-path - (Optional) FastCGI application path that processes the request. The functionality is dependent on the value of the bind-path parameter as follows:
If only app-path is specified, the plug-in creates FastCGI applications, that listens to UNIX Domain Sockets created by the plug-in. This parameter however is accepted only on UNIX platform. On Windows, an error message is logged.
If both app-path and bind-path are specified, the plug-in starts the specified FastCGI application process and binds them to the specified bind-path.
If only bind-path is specified, the FastCGI application is considered to be running remotely. So, the plug-in will not start the FastCGI application process.
If “app-path“ and “bind-path“ both are not specified, then the plug-in logs an error message.
app-args — (Optional) Values that are passed as the arguments to the FastCGI application process. Multiple app-args parameters are allowed. The format for the multiple app-args parameters is app-args="value" app-args="value" ...
bind-path - (Optional) Can be a Unix Domain Socket name or of the form “host:port“. The description of " app-path“ parameter explains the usage of “bind-path“ parameter. Note that the Unix Domain Socket name is applicable only on UNIX platforms. On Windows platforms, bind-path must be specified as “host:port ".
min-procs - (Optional) Integer specifying the minimum number of FastCGI application processes to be created. Defaults to 1.
max-procs - (Optional) Integer specifying the maximum number of FastCGI application processes that can be created at any time. The integer value must be equal to or greater than min-procs. Defaults to 1.
chroot - (Optional) Used to set the root directory of the chroot FastCGI server application processes. Defaults to the Web Server's root directory.
user - (Optional) Specifies the user ID the FastCGI application runs as. Defaults to Web Server's user ID.
group - (Optional) The FastCGI application will be running under the specified group. Defaults to Web Server's group.
nice - (Optional) Specifies the nice/ priority value of FastCGI application processes.
listen-queue - (Optional) Integer specifying the listen queue size for the socket. The default value for this parameter is 256.
app-env - (Optional) Value pairs that are passed as environment variables to the FastCGI application process. Multiple “app-env“ parameters are allowed. The format for multiple app-env parameters is app-env="name=value" app-env="name=value"....
reuse-connection - (Optional) Boolean value that determines if connections to FastCGI applications are reused. False (0, false, no) indicates that the connections to FastCGI applications are closed after each request. True (1, true, yes) indicates that existing connections are reused for new requests. Default is false. See also connection-timeout.
connection-timeout - (Optional) If “reuse-connection " is set to True, then this value specifies the timeout value in seconds for the pooled connections. If a connection is idle for the specified amount period of time, then the plug-in closes the connection. The default value for this parameter is 5 seconds. See also reuse-connection .
resp-timeout - (Optional) Integer that represents the FastCGI server response timeout in seconds. If there is no response from the FastCGI application within the specified period of time, the request is discarded. The default value for this parameter is 5 minutes..
restart-interval - (Optional) Integer that represents the time interval (in minutes) after which the FastCGI application is restarted. The default value for this parameter is 60 minutes (1 hour). If the value for this parameter is set to zero, the FastCGI application is not forced to restart.
req-retry - (Optional) Integer that represents the number of times the plug-in should resend the request when the FastCGI application rejects the request. The default value for this parameter is zero.
The error-fastcgi Server Application Function (SAF) accepts the following parameters:
error-url - Specifies the page, URI or URL to be displayed in case of if a failure or error occurs. The value of this parameter can be an absolute path, a path relative to docroot, or an URL or URI.
error-reason - (Optional) String that represents the FastCGI protocol error. This string is used to differentiate error URLs to be displayed, in case of any plug-in errors.
This section provides a list of all the valid "error-reason" strings and their descriptions:
“Missing or Invalid Config Parameters” : whenever app-path and bind-path are not specified.
“Stub Start Error” : failure to start the Fastcgisub process.
“Stub Connection Failure” : unable to connect to Fastcgistub.
“No Permission” : FastCGI application or the Fastcgisub has no execute permission.
“Stub Request Handling Error” : unable to send the request to stub, received invalid or no response from the stub for a request, and so on.
“Set Parameter Failure” : when set user, group, chroot, nice and so on fail.
“Invalid user and/or group” : when user or group is invalid.
“Server Process Creation Failure” : FastCGI application execution failure or the FastCGI application is unable to bind to the specified address.
“Fastcgi Protocol Error” : FastCGI application contains header with invalid FastCGI version or the role.
“Internal Error” : unable to open the file to be sent to the filter application or any other unknown errors..
FastCGI plug-in is bundled with Web Server 7.0. The plug-in is installed at the following location:
32 bit FastCGI plug-in binaries are installed under <install_dir>/plugins/fastcgi directory. |
64 bit Solaris SPARC FastCGI plug-in binaries are installed under <install_dir>/lib/plugins/fastcgi/64 directory. |
The following FastCGI binaries are installed :
libfastcgi.so (for Solaris/Linux) |
fastcgi.dll(for Windows) |
Fastcgistub.exe(for Windows) |
libfastcgi.sl(for HP-UX) |
Fastcgistub (executable) |
The FastCGI plug-in is configured using the Web Server configuration files located under <instance-dir>/config directory. To configure the FastCGI plug-in, perform the following steps:
Use “load-modules” Init function to load the FastCGI plug-in shared library.
Init fn=flex-init access="access" format.access="%Ses->client.ip% - %Req->vars.auth-user% [%SYSDATE%] \"%Req->reqpb.clf-request%\" %Req->srvhdrs.clf-status% %Req->srvhdrs.content-length%" Init fn="load-modules" shlib="libJava EEplugin.so" shlib_flags="(global|now)" Init fn="load-modules" shlib="libfastcgi.so" shlib_flags="(global|now)"
Edit the mime.types file to specify the MIME mapping. Modifying the MIME type mapping is an optional step.
For Example,
#--Sun Microsystems Inc. MIME Information # Do not delete the above line. It is used to identify the file type. # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # type=application/octet-stream exts=bin type=application/astound exts=asd,asn ... ... type=magnus-internal/fastcgi exts=php ... ...
Edit obj.conf file to configure FastCGI specific requests using the plug-in SAFs described in the earlier sections.
An example of modified obj.conf file is shown below:
# # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # You can edit this file, but comments and formatting changes # might be lost when you use the administration GUI or CLI. <object name = "default"> AuthTrans fn="match-browser" browser="*MSIE*" ssl-unclean-shutdown="true" NameTrans fn="ntrans-Java EE" name="Java EE" NameTrans fn="pfx2dir" from="/mc-icons" dir="/ws7/lib/icons" name="es-internal" NameTrans fn="assign-name" from="/fcgi/*" name="fcgi.config" </object> <Object name="fcgi.config"> AuthTrans fn="auth-fastcgi" app-path="/fastcgi/apps/c/simpleAuth" bind-path="localhost:2111" Service fn="responder-fastcgi" app-path="/fastcgi_enabled_php_installation_dir/bin/php" app-env="name1=abc" </object> ...
Note that FastCGI SAFs can be invoked in different ways by defining different objects for different URL patterns or mapping the SAFs to different MIME types.
For more information on obj.conf configuration and syntax, refer to the Administration Configuration File Reference Guide.
Fastcgistub is a process manager that manages the lifecycle of the FastCGI application processes. Fastcgistub logs its messages into Fastcgistub.log file under Web Server's temporary directory. In case of any errors, checking this file can help in debugging the problem.
Problem: FastCGI requests are not getting served
Possible cause and solutions are as follows:
Check if the FastCGI plug-in is loaded. If the following msg appears during Web Server startup, then the plug-in is loaded successfully. Else, check the path to the plug-in library within magnus.conf: FCGI1000: Sun Java System Web Server 7.0 Update 1 FastCGI NSAPI Plugin < build info>
Check if the request mapping is correctly specified within obj.conf. For more information on the obj.conf file, see the Sun Java System Web Server Administrator's Configuration Reference File.
Check the errors log for any possible error messages.
Check the permissions of the stub binary and FastCGI applications. If enough permissions are not given, the plug-in fails to start the stub or the application.
Check the Fastcgistub.log file for any possible errors on the stub side.
If possible, run the FastCGI application in standalone mode and check if it runs without any issues.
If any library dependency errors are thrown, specify the LD_LIBRARY_PATH in the obj.conf as app-env parameter with LD_LIBRARY_PATH=<dependency library paths> value .
Problem: FastCGI application is not getting started.
Possible cause and solutions are as follows:
Check Fastcgistub.log file for the following log messages: |
.. <pid> process startup failure, trying to restart ... Even after trying <n> time(s), <application path> process failed to start...no more retries
One of the reasons for startup failures can be due to the failure to load the dependent library. This issue can be resolved by specifying the appropriate library path(s) as a app-env parameter value to the FastCGI application configured in the obj.conf file. For example:
Service fn="responder_fastcgi" app-path="/fastcgi/c/tux-app" bind-path="localhost:2112" app-env="LD_LIBRARY_PATH=/tuxedo/lib" |
FastCGI applications can be developed using Perl, PHP, C and Java. The following sections briefly describe the procedure to develop the application using some of the popular programming languages.
Stop the Web Server.
Restart the Web Server.
Access the application that has "fcgi" as the application root.
For Example: http://localhost/fcgi/ListDir.php
A typical FastCGI application has the following code structure:
Initialization code Start of response loop body of response loop End of response loop
The initialization code is run only once at the time of the application initialization. Initialization code usually performs time-consuming operations such as opening databases or calculating values for tables or bitmaps. The main task of converting a CGI program into a FastCGI program is to separate the initialization code from the code that needs to run for each request.
The response loop runs continuously, waiting for client requests to arrive. The loop starts with a call to FCGI_Accept, a routine in the FastCGI library. The FCGI_Accept routine blocks program execution until a client requests the FastCGI application. When a client request comes in, FCGI_Accept unblocks, runs one iteration of the response loop body, and then blocks again waiting for another client request. The loop terminates only when a System Administrator or the Web Server kills the FastCGI application.
Download and install the latest FCGI module from CPAN. For ActivePerl, the modules can be downloaded from http://aspn.activestate.com/ASPN/Downloads/ActivePerl/PPM/Zips.
For more information on writing FastCGI applications using Perl, see http://www.fastcgi.com/devkit/doc/fastcgi-prog-guide/
Beginning with PHP 4.3.0, FastCGI became a supported configuration for the PHP engine. To compile the PHP 4.3.x or greater engine with support for FastCGI, include the configure switch --enable-fastcgi as part of the build process, for example:
./configure <other-options> --enable-fastcgi gmake |
After compilation, the php binary will be FastCGI enabled.
When using PHP versions 5.1.2 or earlier (including PHP 4.x) the FastCGI plug-in should be configured with bind-path in host:port format. For example, bind-path = “localhost:3333”.
For PHP versions 5.1.3 and later, the bind-path is optional. If specified, it should not be in “host:port” format. It can be a string. For example, bind-path = “myphpbindpath”.
FastCGI development kit provides APIs to write FastCGI C/Java applications. You can download the kit from http://www.fastcgi.com/devkit/doc/fcgi-devel-kit.htm.
To build the downloaded FastCGI development kit, perform the following steps:
Unpack the tar file. This action creates a new directory called fcgi-devel-kit
Execute this sequence of commands in the fcgi-devel-kit directory:
./configure
make
For more information on writing FastCGI applications using C, see http://www.fastcgi.com/devkit/doc/fcgi-devel-kit.htm#S3
For more information on writing FastCGI applications using Java, see http://www.fastcgi.com/devkit/doc/fcgi-java.htm
This section contains sample FastCGI applications written using PHP, Perl and C.
<?php $dir = "/tmp/"; // Open a known directory, and proceed to read its contents if (is_dir($dir)) { if ($dh = opendir($dir)) { while (($file = readdir($dh)) !== false) { echo "filename: $file : filetype: " . filetype($dir . $file) . "\n"; } closedir($dh); } } ?>
obj.conf snippet for the above example:
<Object name="default"> NameTrans fn="assign-name" from="/fcgi/*" name="responder.fcgi" </Object> <Object name="responder.fcgi"> Service fn="responder-fastcgi" app-path="/foo/fastcgi-enabled-php-installation/bin/php" bind-path="localhost:3431" min-procs=3 </Object>
#!/usr/bin/perl use FCGI; while (FCGI::accept >= 0) { if( $ENV{'HTTP_AUTHORIZATION'} ) { # This value can be further decoded to get the actual # username and password and then # perform some kind of user validation. This program only # checks for the presence of # of this environment param and is not really bothered about its value print( "Status: 200\r\n" ); print( "\r\n" ); } else { print( "Status: 401\r\n" ); print( "WWW-Authenticate: basic realm=\"foo\"\r\n" ); print( "\r\n" ); } }
Example obj.conf settings for the above example:
<Object name="responder.fcgi"> AuthTrans fn="auth-fastcgi" app-path="/fastcgi/apps/auth/SimpleAuth.pl" bind-path="localhost:3432" Service fn="responder-fastcgi" app-path="/foo/fastcgi-enabled-php-installation/bin/php" bind-path="localhost:3433" app-env="PHP_FCGI_CHILDREN=8" min-procs=1 </Object>
On first request to http://localhost/fcgi/php/ListDir.php, the authentication dialogue box is displayed by the browser. After the user enters the username and password, the contents of "/tmp" directory gets listed.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcgi_stdio.h> void main(void) { size_t PageSize = 1024 * 3; char *page; FCGX_Stream *in, *out, *err; FCGX_ParamArray envp; int count=0; page = (char *)malloc(PageSize); if (page == NULL) { printf("Content-type: text/x-server-parsed-html\r\n"); printf("<title>malloc failure</title>"); printf("<h1>Cannot allocate memory to run filter. exiting</h1>"); printf("\r\n\r\n"); exit(2); } while(FCGI_Accept() >= 0) { char *tmp; char *execcgi; char *dataLenStr = NULL; int numchars = 0; int stdinDataSize = 0; int filterDataLen = 0; int dataToBeRead = 0; int x = 0; int loopCount = 0; count++; dataLenStr = getenv("FCGI_DATA_LENGTH"); if(dataLenStr) filterDataLen = atoi(dataLenStr); /* clear out stdin */ while (EOF != getc(stdin)) { stdinDataSize++; } dataToBeRead = filterDataLen; FCGI_StartFilterData(); tmp = page; /** just in case fread or fwrite moves our pointer **/ //start responding printf("Content-type: text/plain\r\n"); printf("\r\n"); /** send a new line at the beginning **/ printf("<title>SIMPLE FILTER</title>"); printf(<h1>This page was Filtered by SimpleFilter FastCGI filter</h1>"); printf("file size=%d<br>", filterDatalen); printf("stdin size=%d<br>, stdinDataSize); while(dataToBeRead > 0 ) { x = 0; page = tmp; if(dataToBeRead > PageSize) x = PageSize; else x = dataToBeRead; numchars = fread((void *)(page), 1, x, stdin); if( numchars == 0 ) continue; /** at this point your data is in page pointer, so do whatever you want with it before sending it back to the server. In this example, no data is manipulated. Only the count of number of times the filter data is read and the total bytes read at the end of every loop is printed. **/ dataToBeRead -= numchars; loopCount++; printf("loop count = %d ... so far read %d bytes <br>", loopCount, (filterDatalen - dataToBeRead)); } printf("\r\n\r\n"); /** send a new line at the end of transfer **/ fflush(stdout); page = tmp; /** restore page pointer **/ memset(page,NULL,numchars); } free(page); }
Example obj.conf settings for the above example.
If this FastCGI application is available on the same machine as where the Web Server is running, then
<Object name=<"filter.fcgi"> Service fn="filter-fastcgi" app-path="/fastcgi/apps/filter/SimpleFilter.exe" bind-path="localhost:3434" app-env="LD_LIBRARY_PATH=/fastcgi/fcgi-2.4/libfcgi/.libs" </Object>
If the application is running on a remote machine, then the following lines of code must be included in the obj.conf file:
<Object name="filter.fcgi"> Service fn="filter-fastcgi" bind-path="<remote-host>:<remote-port>" </Object>
If "FilterThisFile" of size "26868" bytes located under fcgi directory under the Web Server instance's docroot directory, is the file to be filtered, a request to "http://localhost/fcgi/filter/FilterThisFile", produces the following output:
This page was Filtered by SimpleFilter FastCGI filter
file size = 26868 |
stdin size = 0 |
loop count = 1... so far read 3072 bytes |
loop count = 2... so far read 6144 bytes |
loop count = 3... so far read 9216 bytes |
loop count = 4... so far read 12288 bytes |
loop count = 5... so far read 15360 bytes |
loop count = 6... so far read 18432 bytes |
loop count = 7... so far read 21504 bytes |
loop count = 8... so far read 24576 bytes |
loop count = 9... so far read 26868 bytes |