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" ); } }
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.
#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 |