跟很多协议类似, cgi 协议也由 Header 和Body组成,其中Header为固定格式。
CGI Header
字段 | 长度 | 说明 |
version | 1 bytes | 取值一般为1 |
type | 1 bytes | |
requestId | 2 bytes | Big Endians |
contentLen | 2 bytes | Big Endians |
PaddingLen | 1 bytes | |
reserved | 1 bytes | 预留字段 |
其中type的可能取值如下:
值 | 名称 | 说明 |
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协议
字段 | 长度 | 说明 |
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
协议格式如下:
字段 | 长度 | 说明 |
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