【一】FastCGI协议

2019-10-14  本文已影响0人  Michael_abc

目录

1.介绍

FastCGI全程Fast Common Gateway Interface。FastCGI协议是由CGI协议发展而来。为网络应用提供高性能的支持而不需要受到web服务器的api限制。
该协议规范是一个很狭窄的目标:从应用的观点说明位于一个FastCGI接口和一个Web服务器(支持FastCGi协议)之间的接口。许多与FastCGI相关联的web服务器特性,例如应用管理设施,没有做任何事情在应用到web服务器接口上,这里不做描述。
这个规范是对Unix(更准确地,对支持伯克利socket的POSIX系统),说明的主体是一个简单的通信协议,它是依赖字节的顺序和可以扩展到其他系统。
我们会介绍FastCGI通过比较它和传统的Unix实现的CGI/1.1。FastCGI是被设计去支持长连接的应用进程,这是个主要的不同相较与传统Unix实现的CGI/1.1,它构建一个应用进程,用来响应一个请求然后退出。
FastCGI进程的初始化的状态是比CGI/1.1进程的初始化的状态更简朴的,因为FastCGI的进程不会启动生命连接任何事情。它不会按照惯例的打开文件 stdout,stdin和stderr。它也不会接受许多的信息通过环境变量。初始化状态的关键的部分在FastCGI进程是开始监听socket,通过他来接受来自web服务器的接连。
在FastCGI进程接受连接在它的socket之后,进程执行一个简单的协议接受和发送数据。协议提供两个目的,第一:协议多路复用单个传输连接在几个独立的FastCGI请求,这个支持应用有能力去处理并行的请求用事件驱动或多线程编程技术。第二:在每个请求协议提供几个独立的数据流在每个方向。这种方式,举个例子,stdout和stdin两者数据通过一个传输连接从应用到web服务器而不是像CGI/1.1那样需要各自的通道。
一个FastCGI扮演这个几个定义好的角色中的一个。最熟悉的是响应者角色,在该角色下应用接受所有关于一个HTTP请求信息和产生一个HTTP响应。比如CGI/1.1扮演的角色。第二个角色是授权者,在该角色下,应用接受所有关于一个HTTP请求的信息和产生一个已授权或未授权的决定。第三个角色是过虑者,在该角色下,应用接受所有关于一个HTTP请求加一个额外数据流来着一个文件存储在web服务器的信息和产出一个过滤后的数据流版本作为一个HTTP响应。这个框架是可扩展以至于更多的FastCGI能被以后再定义。
在这个说明的剩余部分项目“FastCGI应用”,“应用进程”或“应用服务者”是缩写为“应用”,无论何时这样不会引起混乱。

2.初始化状态

2.1.参数列表

通过默认web服务器创建一个参数列表包含单个元素,应用的名字,作为可运行路径名的最后一个组件。web服务器可提供一种方式去说明啊一个不同的应用名或一个更多复杂的参数列表。标记文件执行通过web服务器可能被一个编译器文件(一个文本文件以字符#!开始),在这种情况下应用的参数是构建作为描述的在execve主页。

2.2.文件描述符

web服务器只留下一个文件描述符,CGI_LISTENSOCK_FILENO,当应用开始执行时打开,这个描述符涉及如去监听由web服务器创建的socket。FCGI_LISTENSOCK_FILENO等于STDIN_FILENO,标准的描述符STDIN_FILENO和STDERR_FILENO被关闭当应用开始执行。一个可靠的方法对于应用是决定是否它是被引用用CGI或FastCGI是去调用getpeername(FCGI_LISTENSOCK_FILENO),当返回-1并设置errno为ENOTCONN 对于FastCGI应用。web服务器的可靠的传输选择,Unix流通道(AF_UNIX)或TCP/IP(AF_INET)对于FastCGI应用。

2.3.环境变量

web服务器可用环境变量来传输参数给应用,这个说明定义一个例如FCGI_WEB_SERVER_ADDRS;我们期望更多的被定义随着规范的发展和进步。web服务器可提供一种方式去绑定其他的环境变量,例如PATH变量。

2.4.其他状态

web服务器可提供一种方式去说明一个应用初始化进程状态的其他组件,例如进程的优先级,用户ID,组ID,根目录和工作目录。

3.协议基础

3.1.表达式

3.1表达式
我们用C语言表达定义协议消息格式,所以的结构元素被定义在项目的无符号字符类型,是被安置在其中以至ISO C编译器放置它们在明显的方法中,没有覆盖。第一个字节定义在结构中是传输的第一次,第二个字节是第二次,以此类推。我们用两个约定去缩写我们的定义。
第一,当两个相邻的结构组件是被命名表示性的期望为前缀“B1”和“B2”,它意味着两个组件可被看作为一个数字,计算为B1<<8+B0。这个单个数字的名字是组件的名字,减去前缀。这个约定的概括在一个明显方式去处理这个数字代表在超过两个字节。第二,为扩展C结构允许格式

struct {
            unsigned char mumbleLengthB1;
            unsigned char mumbleLengthB0;
            ... /* other stuff */
            unsigned char mumbleData[mumbleLength];
};

意味着一个可变长度的结构,这里的组件长度是通过表明更早的组件或组件组被决定。

3.2.接受传输连接

一个FastCGI应用调用函数accept()在socket引用上通过文件描述符FCGI_LISTENSOCK_FILENO去接受新的传输连接。如果accept()成功,FCGI_WEB_SERVER_ADDRS 环境变量被绑定,应用立刻表现如下特殊的操作:

3.3.记录

应用执行请求需要从web服务器用一个简单协议。协议的详细依赖在应用的角色,
但是粗略的说web服务器第一次发送参数和其他数据给应用,应用发送结果数据给web服务器和最后地应用发送给web服务器一个这个请求结束的标志。

所有流通通过传输连接的数据是被传输在FastCGI记录。FastCGI记录完成两个事情,第一,记录复用传输连接在多个独立的FastCGI请求。这个多路复用支持应用有能力去处理并行请求用事件驱动或多线程编程技术。第二,记录提供多个独立的数据流在每个方向在一个请求内,这个方式,举个例子,stdout和stderr数据能通过单个传输连接从应用到web服务器,而不是用不同的连接。

typedef struct {
            unsigned char version;
            unsigned char type;
            unsigned char requestIdB1;
            unsigned char requestIdB0;
            unsigned char contentLengthB1;
            unsigned char contentLengthB0;
            unsigned char paddingLength;
            unsigned char reserved;
            unsigned char contentData[contentLength];
            unsigned char paddingData[paddingLength];
        } FCGI_Record;

一个FastCGI记录由一个固定长度的前缀设置通过一个变量内容的数字和追加的字节。一个揭露包含七个组件:

填充

协议允许发送者填充他们发生的记录,需要接受者去解释这个paddingLength和跳过这个paddingData,填充允许发送者去保持数据整齐为了更高效的处理,X窗系统的经验显示了对其的表现优势。我们推荐记录以8位字节的倍数来填充边界。固定长度的部分的FCGI_Record是8个字节。

管理请求ID

web服务器重新使用FastCGI请求ID,应用保持每个请求ID当前状态追踪在给的传输连接上,一个请求ID R变成活跃当应用受到一个记录{FCGU_BEGIN_REQUEST,R,...}和变成不活跃当应用发送一个记录{FCGU_END_REQUEST,R,...}给web服务器。当一个请求ID R 是不活跃的,应用忽略记录ID==R,期望对于FCGU_BEGIN_REQUEST记录仅仅是描述的。web服务器企图去保持FastCGI请求IDs 小,这个方式使应用能保持追踪请求ID状态用小的数组而不是长的数组或者是哈希表。一个应用也有选项的接受仅仅在请求在一个时间,在这情况下应用简单的检查进入的requestId值对比与当前的请求Id。

记录的类型

这儿有两个有用方式的分类FastCGI记录类型。
第一个目的是在管理和应用记录之间。一个管理记录保持信息是没有明确说明的对于任何web服务器请求,例如信息关于协议的能力的应用,一个应用记录包括信息关于一个详细的请求,表示通过requestId组件。
管理记录由一个requestId为0的值,也被称为空请求ID,应用记录有非零的requestId。
第二目的是在离散的和流的记录之间。一个离散的记录包含有用的信息单元数据。一个流记录是流的一部分,一个序列的零活更多的非空记录的流类型,支持一个空的记录的流类型contentData 组件的流记录,当连接从一个字节序列,这个自己叙事是流的值,因此流的值是独立的在许多记录它所包含的或它的字节是被分隔在在非空的记录之中。
这里有两种分类是独立的,在记录类型的定义在FastCGI协议的版本中,所有的管理记录记录类型也是离散的记录类型。几乎所有的应用记录类型是流记录类型,但是三个应用记录是离散的,没有东西阻止定义管理记录类型,该类型是协议的某些新版本中的流。

3.4.名字-值对

在许多的角色,FastCGI应用需要读和写变动的数字对的可表长度值,所以它是有用的对于采用一个标准的格式去编码一个名字-值得对。FastCGI传送一个名字-值得对作为名字的长度,根据值的长度,根据名字,根据值。127字节的长度和少于被编码在一个字节的,当更长长度总是被编码在四个字节中。

        typedef struct {
            unsigned char nameLengthB0;  /* nameLengthB0  >> 7 == 0 */
            unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */
            unsigned char nameData[nameLength];
            unsigned char valueData[valueLength];
        } FCGI_NameValuePair11;

        typedef struct {
            unsigned char nameLengthB0;  /* nameLengthB0  >> 7 == 0 */
            unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
            unsigned char valueLengthB2;
            unsigned char valueLengthB1;
            unsigned char valueLengthB0;
            unsigned char nameData[nameLength];
            unsigned char valueData[valueLength
                    ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
        } FCGI_NameValuePair14;

        typedef struct {
            unsigned char nameLengthB3;  /* nameLengthB3  >> 7 == 1 */
            unsigned char nameLengthB2;
            unsigned char nameLengthB1;
            unsigned char nameLengthB0;
            unsigned char valueLengthB0; /* valueLengthB0 >> 7 == 0 */
            unsigned char nameData[nameLength
                    ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
            unsigned char valueData[valueLength];
        } FCGI_NameValuePair41;

        typedef struct {
            unsigned char nameLengthB3;  /* nameLengthB3  >> 7 == 1 */
            unsigned char nameLengthB2;
            unsigned char nameLengthB1;
            unsigned char nameLengthB0;
            unsigned char valueLengthB3; /* valueLengthB3 >> 7 == 1 */
            unsigned char valueLengthB2;
            unsigned char valueLengthB1;
            unsigned char valueLengthB0;
            unsigned char nameData[nameLength
                    ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
            unsigned char valueData[valueLength
                    ((B3 & 0x7f) << 24) + (B2 << 16) + (B1 << 8) + B0];
        } FCGI_NameValuePair44;

高顺序字的顺序的第一个字节的长度表明长度的编码,一个高位零含有一个字节编码,一个四字节编码。这个名字-值对格式运行发送者传送二进制值在不用附加编码情况下。是可使接受者能立刻定位正确存储数量甚至为大的值。

3.5.关闭传输连接

web服务器控制传输连接的生命周期。web服务器能关闭一个连接当没有请求是活跃的。
或web服务器能代表关闭授权给应用(看FCGI_BEGIN_REQUEST)。在这种情况下应用关闭连接在最后说明请求。这个灵活的考虑一个多样的应用类型。简单的应用会操作一个请求在一个时间和接受一个新的传输连接对没有请求。更复杂的应用会处理并行的请求,通过一个或多个传输连接,会保持传输连接打开在长时间的周期。一个简单的应用得到一个重要的表现增长通过关闭传输连接当他已经完成写入它的响应时。
web服务器需要控制连接生命周期在一个长连接中。当一个应用关闭一个连接或者找到一个呗关闭的连接时,应用初始化按一个新的连接。

4.管理记录类型

4.1.FCGI_GET_VALUES,FCGI_GET_VALUES_RESULT

web服务器能查询在应用中特殊的变量,服务者会典型的执行一个茶轩在应用开始的时候为了自动的确定系统层面的配置。应用接受通过发送一个记录{FCGI_GET_VALUES, 0, …},一个FCGU_GET_VALUES记录的contentData部分包括一系列空值的名字-值的对。应用响应通过提供一个值来发送一个记录{FCGI_GET_VALUES_RESULT, 0, …},如果应用不能理解包含在查询中的一个变量名,它会从响应中忽略这个名字。FCGI_GET_VALUES是被设计去允许一个开放变量的结束设置,,这个初始化设置提供信息去帮
助服务器执行应用和连接管理:

一个应用可能接受FCGI_GET_VALUES 记录在任何时间。这个应用的响应应该不涉及应用本身,而只涉及FastCGI库。

4.2.FCGU_UNKOWN_TYPE

管理记录的设置是这个协议的成长在特性版本中,去提供这个进化,协议包括FCGI_UNKOWN_TYPE管理记录。当一个应用受到一个管理记录,这记录类型为T,应用无法理解,应用响应{FCGI_UNKNOWN_TYPE, 0, {T}}。
一个FCGU_UNKOWN_TYPE记录的contentData组件格式如下:

        typedef struct {
            unsigned char type;    
            unsigned char reserved[7];
        } FCGI_UnknownTypeBody;

类型组件是无法识别的管理组件类型。

5.应用记录类型

5.1.FCGI_BEGIN_REQUEST

web服务器发送一个FCGI_BEGIN_REQUEST记录开始一个请求。
FCGI_BEGIN_REQUEST记录的contentData组件有如下格式

        typedef struct {
            unsigned char roleB1;
            unsigned char roleB0;
            unsigned char flags;
            unsigned char reserved[5];
        } FCGI_BeginRequestBody;

这个角色组件设置了web服务器期望应用扮演的角色,当前的角色定义是:

角色是被描述更多细节在章节6中。
这个标志位组件包含一个字来控制连接关闭:flags&FCGI_KEEP_CONN:如果是零,应用关闭连接在响应这个请求之后,如果非零,应用不会关闭连接在响应之后,web服务器保持响应能力在这个链接上。

5.2.名字-值的对 流:FCGI_PARAMS

FCGU_PARAMS
是个流记录被作用在发送名字-值得对从web服务器到应用。名字-值的对是被发送流一个一个发送切没有明确顺序。

5.3字节流:FCGI_STDIN,FCGI_DATA,FCGI_STDOUT,FCGI_STDERR

5.4.FCGI_ABORT_REQUEST

web服务器发送一个FCGI_ABORT_REQUEST 记录投结束请求,在收到{FCGI_ABORT_REQUEST,R}之后,应用响应尽可能快的{FCGI_END_REQUEST, R, {FCGI_REQUEST_COMPLETE, appStatus}}。这是真实的一个响应从应用,非低级知识面从FastCGI库。
一个web服务器结束一个FastCGI请求当一个http客户端关闭它的传输连接在FastCGI请求已经跑在代表那个客户端。这种情况可能看起来不常见,所有FastCGI是缓慢的,但是FastCGI应用能被延时和另一个系统通信或执行一个服务推送。当web服务器不是一个多路复用的请求通过一个传输连接,web服务器能终止这个请求通过关闭请求的传输连接。但是随着多路复用请求,关闭传输连接已经不好的影响在关闭在连接上的所有的请求。

5.5.FCGI_END_REQUEST

应用发送FCGI_END_REQUEST记录去终结一个请求,要么是因为应用已经处理了请求,或者因为应用已经拒绝了请求。
FCGI_END_REQUEST记录的contentData组件有如下格式:

        typedef struct {
            unsigned char appStatusB3;
            unsigned char appStatusB2;
            unsigned char appStatusB1;
            unsigned char appStatusB0;
            unsigned char protocolStatus;
            unsigned char reserved[3];
        } FCGI_EndRequestBody;

appStatus组件是一个应用级别的状态码,每个角色记录appSstatus的用法
protocolStatus组件是协议级别的状态码;操作protocolStatus的值是:

6.角色是被描述更多细节在章节6中。

6.1角色协议

角色协议仅包含应用记录类型的记录,它们本质上用流来传输所有的数据。为了是协议可靠和简单的应用编程,交涉协议被定义去用贴近连续的编程,在协议中严格顺序的编程。应用接受它的第一次输出,然后它的第二次,以此类推。直到塔接受完毕。相似的,应用发送它的第一次输出,然后第二次,以此类推。直到发送完毕。输入不是对于彼此不是交错的,输出也不是。连续的编组角色对一些FastCGI角色是过于限制的。因为FastCGI编程能写stdout和stderr没有时间性的限制。所以角色协议用FCGI_STDOUT和FCGI_STDERR允许这两个流被交错。
所有的角色协议用FCGI_STDERR流仅是stderr被用作传统的应用编程的一种方式。去报告一个应用级别的错误用可理解的方式。FCGI_STDERR流的使用是可选的。,如果一个应用没有错误去报告,它要么不发送FCGI_STDERR记录或者零长度的FCGI_STDERR记录。

当一个角色协议调用去传送一个其他流而不是FCGI_STDERR,至少是一个流类型的记录总是被传送的,甚至如果流是空的。再者在可靠协议的和简单的应用编程这些有兴趣的方面,角色协议是被设计去贴近请求和响应。在真实的请求和响应协议,应用接受所有的输入记录在发送第一个输出记录之前。请求和响应协议不总是运行流水线。请求和响应视同FCGI_PARAMS去传输文本型的值,例如CGI程序从环境变量获得的值,值得长度不包括结束的空字节。值它本身也不包括空的字节。一个应用需要去提供environ(7)格式的名字-值的对必须插入一个等于的签名在名字和值还有追加的空字节在值得后面。角色协议不支持无法解析的头特性的CGI,FastCGI应用设置响应状态用Status和location CGI头组。

6.2.响应者

一个响应者的FastCGI应用有相同的目的作为CGI/1.1程序:她接受所有关联一个HTTP请求的信息和生产一个HTTP响应。它的足够去解释每个CGI/1.1的元素怎样去模仿作为一个响应者:

6.3.授权者

一个授权者FastCGI应用接受所有关于HTTP请求的信息和生产一个授权/非授权的决定。在这种情况下一个授权决定授权者也能和HTTP请求关联名字-值的对。当给一个非授权的决定时授权者发送一个完全的响应给HTTP客户端。只从CGI/1.1定义了一种近乎完美的好方法去表示联系HTTP请求的信息,授权者用相同的表示:

Variable-AUTH_METHOD: database lookup

传输“database lookup”用名字AUTH_METHOD,这个服务例如名字-值得对是与HTTP请求有联系,包括在随后的CGI或者FastCGI请求执行在处理HTTP请求时。当应用给一个200响应,服务忽略这些以Variable-为前缀的响应头,也会忽略任何响应内容。对与授权者响应状态值是非200(OK),web服务器拒绝访问并发送响应状态,头和内容返回给HTTP客户端。

6.4.过虑者

一个过虑者FastCGI应用接受所有与HTTP请求相关的信息,加上一个额外的数据流从在web服务器上的文件存储,生产一个过滤后的版本的数据流作为HTTP响应。一个过虑者是和响应者具有类似的功能,都是处理数据文件作为参数。不同的是作为一个过虑者,数据文件和过虑者自己都能被控制访问使用web服务器的访问控制机制,当一个响应者获得一个数据文件的名字作为一个参数时必须处理它自己的访问控制检查在这个数据文件上。
过虑者的步骤处理是与响应者是相似的。第一服务表示过虑者用环境变量,然后标准的输入(正常的从POST数据),最后数据文件输入:

7.错误码

一个FastCGI应用以零状态退出标示它已经完成目的,比如为了执行一种粗略的垃圾回收。
一个FastCGI应用以非零状态退出似乎除了崩溃。一个web服务器或其他应用怎么管理响应给一个以零或非零退出码是不在这次规范的范围内。
一个web服务器能请求一个FastCGI应用退出通过发送给它一个STGERM信号。如果应用忽略STGTERM信号web服务器能再发送SIGKILL信号。
FastCGI应用报告应用级别错误通过FCGI_STDERR流和FCGI_END_REQUEST的appStatus组件,在许多情况下一个错误会被直接报告通过FCGI_STDOUT流。
在UNIX,应用报告基础级别错误,包括FastCGI协议错误和格式错误在FastCGI环境版本,通过syslog。依赖错误的级别,应用能要么继续要么以非零码退出。

8.类型和常量

/*
 * Listening socket file number
 */
#define FCGI_LISTENSOCK_FILENO 0

typedef struct {
    unsigned char version;
    unsigned char type;
    unsigned char requestIdB1;
    unsigned char requestIdB0;
    unsigned char contentLengthB1;
    unsigned char contentLengthB0;
    unsigned char paddingLength;
    unsigned char reserved;
} FCGI_Header;

/*
 * Number of bytes in a FCGI_Header.  Future versions of the protocol
 * will not reduce this number.
 */
#define FCGI_HEADER_LEN  8

/*
 * Value for version component of FCGI_Header
 */
#define FCGI_VERSION_1           1

/*
 * Values for type component of FCGI_Header
 */
#define FCGI_BEGIN_REQUEST       1
#define FCGI_ABORT_REQUEST       2
#define FCGI_END_REQUEST         3
#define FCGI_PARAMS              4
#define FCGI_STDIN               5
#define FCGI_STDOUT              6
#define FCGI_STDERR              7
#define FCGI_DATA                8
#define FCGI_GET_VALUES          9
#define FCGI_GET_VALUES_RESULT  10
#define FCGI_UNKNOWN_TYPE       11
#define FCGI_MAXTYPE (FCGI_UNKNOWN_TYPE)

/*
 * Value for requestId component of FCGI_Header
 */
#define FCGI_NULL_REQUEST_ID     0

typedef struct {
    unsigned char roleB1;
    unsigned char roleB0;
    unsigned char flags;
    unsigned char reserved[5];
} FCGI_BeginRequestBody;

typedef struct {
    FCGI_Header header;
    FCGI_BeginRequestBody body;
} FCGI_BeginRequestRecord;

/*
 * Mask for flags component of FCGI_BeginRequestBody
 */
#define FCGI_KEEP_CONN  1

/*
 * Values for role component of FCGI_BeginRequestBody
 */
#define FCGI_RESPONDER  1
#define FCGI_AUTHORIZER 2
#define FCGI_FILTER     3

typedef struct {
    unsigned char appStatusB3;
    unsigned char appStatusB2;
    unsigned char appStatusB1;
    unsigned char appStatusB0;
    unsigned char protocolStatus;
    unsigned char reserved[3];
} FCGI_EndRequestBody;

typedef struct {
    FCGI_Header header;
    FCGI_EndRequestBody body;
} FCGI_EndRequestRecord;

/*
 * Values for protocolStatus component of FCGI_EndRequestBody
 */
#define FCGI_REQUEST_COMPLETE 0
#define FCGI_CANT_MPX_CONN    1
#define FCGI_OVERLOADED       2
#define FCGI_UNKNOWN_ROLE     3

/*
 * Variable names for FCGI_GET_VALUES / FCGI_GET_VALUES_RESULT records
 */
#define FCGI_MAX_CONNS  "FCGI_MAX_CONNS"
#define FCGI_MAX_REQS   "FCGI_MAX_REQS"
#define FCGI_MPXS_CONNS "FCGI_MPXS_CONNS"

typedef struct {
    unsigned char type;    
    unsigned char reserved[7];
} FCGI_UnknownTypeBody;

typedef struct {
    FCGI_Header header;
    FCGI_UnknownTypeBody body;
} FCGI_UnknownTypeRecord;

9.引用

The WWW Common Gateway Interface at W3C

A.表:记录类型的属性

如下的图表列出了所有的记录类型和标示这每一个属性:

                               WS->App   management  stream

        FCGI_GET_VALUES           x          x
        FCGI_GET_VALUES_RESULT               x
        FCGI_UNKNOWN_TYPE                    x

        FCGI_BEGIN_REQUEST        x
        FCGI_ABORT_REQUEST        x
        FCGI_END_REQUEST
        FCGI_PARAMS               x                    x
        FCGI_STDIN                x                    x
        FCGI_DATA                 x                    x
        FCGI_STDOUT                                    x 
        FCGI_STDERR                                    x     

B.典型的协议信息流

示例的其他符合的惯例

1.一个简单的请求,没有数据再stdin,且是一个成功的响应

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, 0}}
{FCGI_PARAMS,          1, "\013\002SERVER_PORT80\013\016SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_STDIN,           1, ""}

    {FCGI_STDOUT,      1, "Content-type: text/html\r\n\r\n<html>\n<head> ... "}
    {FCGI_STDOUT,      1, ""}
    {FCGI_END_REQUEST, 1, {0, FCGI_REQUEST_COMPLETE}}

2.相似与例子1,但是这个时间数据再stdin。web服务器选择发送参数用更多的FCGI_PARAMS记录在之前:

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, 0}}
{FCGI_PARAMS,          1, "\013\002SERVER_PORT80\013\016SER"}
{FCGI_PARAMS,          1, "VER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_STDIN,           1, "quantity=100&item=3047936"}
{FCGI_STDIN,           1, ""}

    {FCGI_STDOUT,      1, "Content-type: text/html\r\n\r\n<html>\n<head> ... "}
    {FCGI_STDOUT,      1, ""}
    {FCGI_END_REQUEST, 1, {0, FCGI_REQUEST_COMPLETE}}

3.相似与例子1,但是这个时间应用检测到错误,应用记录这个消息在stderr上,返回一个页面给客户端,返回一个非零的退出状态给web服务器。
应用悬着去发送页面使用更多的FCGI_STDOUT记录:

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, 0}}
{FCGI_PARAMS,          1, "\013\002SERVER_PORT80\013\016SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_STDIN,           1, ""}

    {FCGI_STDOUT,      1, "Content-type: text/html\r\n\r\n<ht"}
    {FCGI_STDERR,      1, "config error: missing SI_UID\n"}
    {FCGI_STDOUT,      1, "ml>\n<head> ... "}
    {FCGI_STDOUT,      1, ""}
    {FCGI_STDERR,      1, ""}
    {FCGI_END_REQUEST, 1, {938, FCGI_REQUEST_COMPLETE}}

4.两个实例的例子1,多路复用在一个连接上。第一个请求是比第二个更困难,所以应用结束请求的完成顺序:

{FCGI_BEGIN_REQUEST,   1, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          1, "\013\002SERVER_PORT80\013\016SERVER_ADDR199.170.183.42 ... "}
{FCGI_PARAMS,          1, ""}
{FCGI_BEGIN_REQUEST,   2, {FCGI_RESPONDER, FCGI_KEEP_CONN}}
{FCGI_PARAMS,          2, "\013\002SERVER_PORT80\013\016SERVER_ADDR199.170.183.42 ... "}
{FCGI_STDIN,           1, ""}

    {FCGI_STDOUT,      1, "Content-type: text/html\r\n\r\n"}

{FCGI_PARAMS,          2, ""}
{FCGI_STDIN,           2, ""}

    {FCGI_STDOUT,      2, "Content-type: text/html\r\n\r\n<html>\n<head> ... "}
    {FCGI_STDOUT,      2, ""}
    {FCGI_END_REQUEST, 2, {0, FCGI_REQUEST_COMPLETE}}
    {FCGI_STDOUT,      1, "<html>\n<head> ... "}
    {FCGI_STDOUT,      1, ""}
    {FCGI_END_REQUEST, 1, {0, FCGI_REQUEST_COMPLETE}}

C.英语原文原文

英语原文

上一篇 下一篇

猜你喜欢

热点阅读