跟很多协议类似,cgi协议也由Header和Body组成,其中Header为固定格式。
CGI Header
<table><thead>字段
长度
说明
version
1 bytes
取值一般为1
type
1 bytes
requestId
2 bytes
Big Endians
contentLen
2 bytes
Big Endians
PaddingLen
1 bytes
reserved
1 bytes
预留字段
其中type的可能取值如下:
<table><thead>值
名称
说明
1
FCGIBEGINREQUEST
开始请求
2
FCGIABORTREQUEST
异常终止请求
3
FCGIENDREQUEST
正常终止请求
4
FCGI_PARAMS
传递参数
5
FCGI_STDIN
POST内容传递
6
FCGI_STDOUT
正常响应内容
7
FCGI_STDERR
错误输出
8
FCGI_DATA
9
FCGIGETVALUES
10
FCGIGETVALUES_RESULT
11
FCGIUNKNOWNTYPE
通知webserver所请求type非正常类型
CGI Body
StartRequestRecord协议
<table><thead>字段
长度
说明
role
2 bytes
Big Endians
flags
1 byte
>0表示长连接,否则短连接
reserved
5 bytes
预留字段
包pack伪码如下:
type RecordBodyStartRequest struct {
Role uint16
Flags byte
}
func (r RecordBodyStartRequest) Encode() []byte {
var ret []byte = make([]byte, 0)
ret = append(ret, byte((r.Role >> 8) & 0xFF))
ret = append(ret, byte(r.Role & 0xFF))
ret = append(ret, r.Flags)
ret = common.AppendByteNums(ret, 0, 5)
return ret
}
SendParamRequest协议
这个协议用来通知php-fpm一些常量,例如:
·SCRIPT_FILENAME
·REQUEST_METHOD
协议格式如下:
<table><thead>字段
长度
说明
name_len
1 bytes OR 4 bytes
长度小于128用一个字节,大于128用4个字节
value_len
同上
同上
name
n bytes
SCRIPTFILENAME/REQUESTMETHOD etc
value
n bytes
/path/to/php etc
包pack伪码如下:
type RecordBodySendParams struct {
Name string
Value string
}
func (r RecordBodySendParams) Encode() []byte {
var name string = r.Name
var value string = r.Value
var ret []byte = make([]byte, 0)
var nameLen int = len(name)
if nameLen < 128 {
ret = append(ret, byte(nameLen))
} else {
ret = append(ret, byte((nameLen >> 24) | 0x80))
ret = append(ret, byte(nameLen >> 16))
ret = append(ret, byte(nameLen >> 8))
ret = append(ret, byte(nameLen))
}
var valueLen int = len(value)
if valueLen < 128 {
ret = append(ret, byte(valueLen))
} else {
ret = append(ret, byte((valueLen >> 24) | 0x80))
ret = append(ret, byte(valueLen >> 16))
ret = append(ret, byte(valueLen >> 8))
ret = append(ret, byte(valueLen))
}
for _, v := range []byte(name) {
ret = append(ret, v)
}
for _, v := range []byte(value) {
ret = append(ret, v)
}
return ret
}
EndRequest 协议
这个协议没有包体,只要将Header中type置为FCGIENDREQUEST即可
There's ALL
基础的协议全部讲完了,剩下的就可以和php-fpm进行简单的通讯了,更多协议格式还请参考官网规定.
Thank You
閱讀更多 蝸牛zzZ 的文章