Sun Java System Web Server 7.0 Update 7 Administrator's Guide

Appendix B FastCGI Plug-in

Introduction

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:

FastCGI plug-in enables 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.

Plug-in Functions (SAFs)

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

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

responder-fastcgi

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

filter-fastcgi

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 response 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

error-fastcgi

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.

FastCGI SAF 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, nice, chdir, rlimit_as, rlimit_core and rlimit_nofile are applicable to UNIX platforms only. On Windows platforms, these parameters are ignored.

The error-fastcgi Server Application Function (SAF) accepts the following parameters:

error-fastcgi SAF Error Reason Strings

This section provides a list of all the valid "error-reason" strings and their descriptions:

Configuring FastCGI Plug-in on Web Server

FastCGI plug-in is packaged with Web Server 7.0. You can configure FastCGI Plug-in on Web Server in one of following ways:

Configuring FastCGI Plug-in on Web Server Manually

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:

Modify the magnus.conf

Use the “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)"

Modify the MIME Type (Optional)

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

...

...

Modify the obj.conf

Edit the 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, see Chapter 6, Syntax and Use of obj.conf, in Sun Java System Web Server 7.0 Update 7 Administrator’s Configuration File Reference.

Configuring Multiple FastCGI Applications

You cannot configure multiple FastCGI applications through the Administration Console or CLI. As a workaround, you can configure multiple applications by modifying the obj.conf file. For example:


<If $uri =~ '^/fcgi/(.*)'>
Service fn="responder-fastcgi"
 app-path="/export/home/bits/fastcgi/fcgi-2.4.0/examples/$1"
 app-env="LD_LIBRARY_LIBRARY_PATH=/export/home/bits/fastcgi/fcgi-2.4.0/libfcgi/.libs"
</If>

The expression creates the <app-path> process, which does not need to be configured separately.


Note –

You cannot configure the same bind-path for multiple applications because it results in startup failure due to a common bind-path.


Configuring the Virtual Hosting Environment

The virtual hosting environment aims to protect potential security and performance problems associated with sharing a PHP engine with several virtual servers.

Using Web Server 7.0 environment variables, you can assign same PHP binary with a separate engine bound to each virtual server. Be sure that each virtual server has its own php.ini file.


Service fn=responder-fastcgi
        app-path="/path/to/php/php_fcgi"
        bind-path="$(lc($urlhost))"
        req-retry=5
        type="*magnus-internal/fastcgi*"
        app-env="PHPRC=/path/to/users/$(lc($urlhost))/config"
        app-env="PHP_FCGI_CHILDREN=5"
        app-env="PHP_FCGI_MAX_REQUEST=200"
        min-procs=1
        restart-interval=10
        bucket="php-bucket"
        rlimit_cpu=60

The Web Server tmp directory now shows Unix domain sockets named after individual virtual servers processing PHP requests. This configuration is possible by using a single PHP FastCGI binary for all users. Thus, the single binary must possess all the required plugins compiled with it. The solution for the previously mentioned difficulty is to ensure that each user has a own copy of the PHP binary as needed.


Service fn=responder-fastcgi
        app-path="/path/to/users/$(lc($urlhost))/php_fcgi"
        bind-path="$(lc($urlhost))"
        req-retry=5
        type="*magnus-internal/fastcgi*"
        app-env="PHPRC=/path/to/users/$(lc($urlhost))/config"
        app-env="PHP_FCGI_CHILDREN=5"
        app-env="PHP_FCGI_MAX_REQUEST=200"
        min-procs=1
        restart-interval=10
        bucket="php-bucket"
        rlimit_cpu=60

It is also possible to allow different PHP binaries for each application by controlling the structure of the URI space.

For example:

If the URI space is structured as:

/app/foo.php

where /app is the name of the overall application and is always the first directory in the URI structure ending with a PHP file.


<If uri~=^/(\w+)/\w+\.php$>
						Service fn=responder-fastcgi
						app-path="/path/to/users/$(lc($urlhost))/$1/php_fcgi"
						bind-path="$(lc($urlhost))_$1"
						req-retry=5
						type=+magnus-internal/fastcgi*"
						app-env="PHPRC=/path/to/users/$(lc($urlhost))/config"
						app-env="PHP_FCGI_CHILDREN=5"
						app-env="PHP_FCGI_MAX_REQUEST=200"
						min-procs=1
						restart-interval=10
						bucket="php-bucket"
						rlimit_cpu=60
</If>

This invokes a specifically built PHP FastCGI binary which binds to a uniquely named Unix domain socket. Thus, there is no interference with another PHP application or another virtual server. However, this process uses up a lot of memory because of many PHP processes around.

Sample Configuration File

This is a sample configuration file that configures PHP with FastCGI.

<If -f $path>
Service type="magnus-internal/php"
    fn="responder-fastcgi"
    app-path="/opt/coolstack/php5/bin/php-cgi"
    bind-path="localhost:3101"
    app-env="PHPRC=/opt/coolstack/php5"
    app-env="PHP_FCGI_CHILDREN=5"
    app-env="PHP_FCGI_MAX_REQUEST=200"
    app-env="FCGI_WEB_SERVER_ADDRS=127.0.0.1"
    req-retry=5
    restart-interval=10
    bucket="php-bucket"

</If>
<Else>
Service type="magnus-internal/php" fn="set-variable" error="404"
</Else>

Troubleshooting FastCGI Plug-in

Fastcgistub is a process manager that manages the lifecycle of the FastCGI application processes. Fastcgistub logs its messages into a Fastcgistub.log file under Web Server's temporary directory. In case there are 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:

  1. Check if the FastCGI plug-in is loaded. If the following message appears during Web Server startup, then the plug-in is loaded successfully. Otherwise, check the path to the plug-in library within magnus.conf: FCGI1000: Sun Java System Web Server 7.0 Update 7 FastCGI NSAPI Plugin < build info>

  2. 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.

  3. Check the errors log for any possible error messages.

  4. 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.

  5. Check the Fastcgistub.log file for any possible errors on the stub side. You can find the log details in <instances>/logs.

  6. 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 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"

Developing FastCGI Applications

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.

ProcedureExecuting a FastCGI Application

  1. Stop the Web Server.

  2. Restart the Web Server.

  3. Access the application that has "fcgi" as the application root.

    For Example: http://localhost/fcgi/ListDir.php

Structure of a FastCGI Application

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.

Using Perl

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/#TheDevKit

Using PHP

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”.

Using C/Java

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:

  1. Unpack the tar file. This action creates a new directory called fcgi-devel-kit

  2. Execute this sequence of commands in the fcgi-devel-kit directory:

    1. ./configure

    2. 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

Configuring FastCGI Plug-in on Web Server from Administration Console

ProcedureTo Configure FastCGI Plug-in from Administration Console

  1. Download the FastCGI enabled Sun Java System Web Server 7.0 PHP Add-On 1.0 from: http://www.sun.com/download/index.jsp

  2. Configure PHP as a FastCGI server on Web Server.

    1. Unpack the phppack-5_2_0*.zip to /export/home


      $ cd /export/home; unzip phppack-5_2_0*.zip
    2. Start the Administration Server.


      $ <webserver-install-root>/admin-server/bin/startserv
    3. Configure the FastCGI handler using Administration Console.

      1. Login to the Administration Console.

      2. Click Edit Virtual Server from Virtual Server Tasks.

      3. Under Virtual Server General Properties, click the Content Handling tab.

      4. Under Content Handling — General Properties, click the FastCGI tab.

      5. Click New to add a new URI with FastCGI handler mapping.

        Enter the following values:

        • Applies To: Select New URI and enter /fastcgi/*

        • Role: Select Responder from the drop-down list.

        • Application Path: Enter /export/home/php/bin/php as the path.

        • Environment Variables: Enter the variable:


          "PHPRC=/export/home/php","LD_LIBRARY_PATH=/export/home/php",
          "LD_LIBRARY_PATH_64=/export/home/php/64"
      6. Click OK. Click Deploy if needed.

  3. Create a symbolic link.


    $ ln -s <webserver-install-root>/samples/fastcgi <webserver-instance-docroot>
  4. Run the samples.

    • Hello World sample URL

      http://<host-name>:<webserver-instance-port>/fastcgi/HelloWorld.php

    • Directory Listing sample URL

      http://<host-name>:<webserver-instance-port>/fastcgi/directory.php

    • Page Counter sample URL

      http://<host-name>:<webserver-instance-port>/fastcgi/pageCounter.php

    • Server Information sample URL

      http://<host-name>:<webserver-instance-port>/fastcgi/serverinfo.php

Configuring FastCGI Plug-in on Web Server from CLI

There are five CLI commands associated with FastCGI handler which are listed below:

ProcedureTo Configure FastCGI Plug-in from CLI

  1. Invoke the following command to create a FastCGI handler.


    wadm> create-fastcgi-handler --config=test --vs=test --uri-pattern=/php/* --role=filter
     --app-path=C:\\php\\phppack-5_2_0-windows-i586\\php\\php-cgi.exe

    A FastCGI handler with role as Filter is created.

    For more information, see CLI Reference, create-fastcgi-handler(1)

  2. Deploy the configuration by invoking the following command.


    wadm> deploy-config test

    Note –

    If you are creating the FastCGI handler for the first time, you should restart the instance after deploying the configuration.


    wadm> restart-instance --config=test localhost

Running FastCGI Enabled PHP Application in Remote Mode

You can run FastCGI enabled PHP in remote mode and configure Sun Java System Web Server. This enables the Web Server to pass requests to the remote PHP engine.

ProcedureTo Run FastCGI Enabled PHP Application

  1. Run FastCGI enabled PHP.


    $ php -b <hostname>:<port> &

    For example:


    $ php -b localhost:4321 &

    Note –

    You can check whether or not the PHP you are using is FastCGI-enabled by running the command:


    $ php -v

    PHP 5.2.5 (cgi-fcgi) (built: May  8 2008 12:50:19)
    Copyright (c) 1997-2007 The PHP Group
    Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies

    In the output, look for cgi-fcgi to confirm.


  2. Configure the Sun Java System Web Server using CLI.

    For example, a Web Server instance named test is created.

  3. Using the CLI, execute the following command:


    wadm> create-fastcgi-handler --config=test --vs=test
     --uri-pattern=/php/* --role=responder --bind-path="localhost:4321"
    wadm> deploy-config test

    A FastCGI handler with the role as Responder is created.

  4. Restart your instance.


    wadm> restart-instance --config=test localhost

    After completing the configuration, you can check if the requests from Web Server are being forwarded to the remote PHP engine.

    1. Place the below sample PHP script in the php subdirectory of your instance docroot, that is, <instance-dir>/docs_directory


      info.php:
      <?php
      phpinfo();
      ?>
    2. Access the remote PHP engine URL: http://localhost:<webserverport>/php/info.php to verify the status of your request.

Sample FastCGI Applications

This section contains sample FastCGI applications written using PHP, Perl and C.

Responder application in PHP (ListDir.php)

<?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>

Authorizer application in Perl (SimpleAuth.pl)

#!/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" );  

   }

}

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 are listed.

Filter application in C (SimpleFilter.c)

#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 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 the 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