Sun Java System Web Server 7.0 Update 3 管理員指南

FastCGI 應用程式範例

本節包含使用 PHP、Perl 和 C 撰寫的 FastCGI 應用程式範例。

使用 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 程式碼片段:

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

使用 Perl 撰寫的 Authorizer 應用程式 (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 設定:

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

第一次向 http://localhost/fcgi/php/ListDir.php 提出請求時,瀏覽器會顯示認證對話方塊。在使用者輸入使用者名稱和密碼後,即會列出「/tmp」目錄內容。

使用 C 撰寫的 Filter 應用程式 (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);
}

上述範例的 obj.conf 設定範例。

如果此 FastCGI 應用程式和 Web 伺服器在同一台機器上執行,則

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

如果該應用程式是在遠端機器上執行,則 obj.conf 檔案中必須包含下列程式碼行:

<Object name="filter.fcgi">
			Service fn="filter-fastcgi" bind-path="<remote-host>:<remote-port>"
</Object>

如果要篩選位於 fcgi 目錄 (此目錄位於 Web 伺服器實例的文件根目錄下) 下大小為「26868」位元組的檔案「FilterThisFile」,則向「http://localhost/fcgi/filter/FilterThisFile」提出請求時,會產生下列輸出:

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