• Home
  • Articles
    • 日志
    • 妍小言
    • 舒小书
    • 浩然说
    • 生活日记
  • All Tags

AJP

01 Jul 2019

Reading time ~2 minutes

协议简述

该协议是基于Apache AJP协议的学习整理版本.AJP是面向数据包设计的,使用二进制字节进行数据传输.端与端之间保持长链接,用以避免套接字创建的开销

请求不是通过连接多路复用的,即将连接分配给特定请求后,在请求处理周期终止之前,不会将其用于任何其他请求.

请求的基本信息比如请求头,请求方法等都以高度精简的形式进行传输(公共字符串被编码为整数)

数据包数据类型

协议中有四种数据类型: bytes, booleans, integers, string和bytes.

  • byte: 单个字节
  • boolean:单字节,1=true;0=false
  • Integer:取值范围是0到2^16 (32768),使用两个字节进行存储
  • string:首先将长度编码为两个字节,然后是字符串+终止符号\0(终止符不计长度)
  • bytes:首先将长度编码为两个字节,然后是数据+终止符号\0(终止符不计长度)

包大小

最大数据包大小为8 * 1024字节(8k).数据包的实际长度在包头中编码.

包头

从客户端发往服务端的包头开始于0x1234,从服务端发往客户端的包头开始于0x4142.在前两个字节之后,有一个带有有效数据包长度的整数.

包格式(客户端 - >服务端)

字节 0 1 2 3 4 ……第(n + 3)
内容 0×12 0x34 长度第一个字节 长度第二个字节 数据

包格式(服务端 - >服务端)

字节 0 1 2 3 4 ……第(n + 3)
内容 0x41 0x42 长度第一个字节 长度第二个字节 数据

对于一个正常的数据包的payload,第一个字节用来指示消息类型.

数据包类型

请求的数据包

Code Type of Packet Meaning
2 Forward Request 使用接下来的数据处理请求
10 CPing 客户端向要求服务端快速响应CPong

响应的数据包

Code Type of Packet Meaning
3 Send Body Chunk 发送数据块作为请求的响应
4 Send Headers 发送响应头数据
5 End Response 标志response的完结
6 Get Body Chunk 发起请求获取请求体内容
9 CPong Reply CPing的响应

请求包结构

AJP13_FORWARD_REQUEST :=
    prefix_code      (byte) 0x02 = 	Forward Request
    method           (byte)
    req_uri          (string)
    remote_addr      (string)
    remote_host      (string)
    server_name      (string)
    server_port      (integer)
    is_ssl           (boolean)
    num_headers      (integer)
    request_headers *(req_header_name req_header_value)
    attributes      *(attribut_name attribute_value)
    request_terminator (byte) OxFF

request_headers具备以下的结构

req_header_name := sc_req_header_name(以下会描述sc_req_header_name映射关系)

sc_req_header_name := 0x000A (integer)

req_header_value := (string)

attributes具备以下结构

attribute_name := attribute_type(如果是请求参数, 后面会跟参数名称,类型为 string)

attribute_value := (string)

请求方法

请求方法,编码为单个字节:

Method Name Code
OPTIONS 1
GET 2
HEAD 3
POST 4
PUT 5
DELETE 6

请求头

对于请求头的结构,首先通过num_headers编码请求头的数量,接下来是一系列req_header_name和req_header_value键值对,其中req_header_name使用数值类型进行编码,编码列表如下:

Name Code value Constant name
accept 0xA001 SC_REQ_ACCEPT
accept-charset 0xA002 SC_REQ_ACCEPT_CHARSET
accept-encoding 0xA003 SC_REQ_ACCEPT_ENCODING
accept-language 0xA004 SC_REQ_ACCEPT_LANGUAGE
authorization 0xA005 SC_REQ_AUTHORIZATION
connection 0xA006 SC_REQ_CONNECTION
content-type 0xA007 SC_REQ_CONTENT_TYPE
content-length 0xA008 SC_REQ_CONTENT_LENGTH
cookie 0xA009 SC_REQ_COOKIE
cookie2 0xA00A SC_REQ_COOKIE2
host 0xA00B SC_REQ_HOST
pragma 0xA00C SC_REQ_PRAGMA
referer 0xA00D SC_REQ_REFERER
user-agent 0xA00E SC_REQ_USER_AGENT

属性

属性可通过多种方式传递,如请求参数,query string, basic认证信息(user:pwd@localhost/path)等.

对于每个属性,都有一个字节代码表示属性的类型,然后是一个字符串来给出它的值.

发送一个特殊的终止代码来发信号通知可选属性列表的末尾(0xFF)

Information Code Value Note
remote_user 0x03 请求认证
auth_type 0x04 请求认证
query_string 0x05  
route 0x06 请求粘性
ssl_cert 0x07  
ssl_cipher 0x08  
ssl_session 0x09  
req_attribute 0x0A 请求参数
ssl_key_size 0x0B  
secret 0x0C  
stored_method 0x0D  
are_done 0xFF request_terminator

响应包结构

AJP13_SEND_BODY_CHUNK := 
  prefix_code   3
  chunk_length  (integer)
  chunk         (bytes)


AJP13_SEND_HEADERS :=
  prefix_code       4
  http_status_code  (integer)
  http_status_msg   (string)
  num_headers       (integer)
  response_headers *(res_header_name header_value)

res_header_name := sc_res_header_name (以下会描述sc_req_header_name映射关系)
sc_res_header_name := 0xA0 (byte)
header_value := (string)

AJP13_END_RESPONSE :=
  prefix_code       5
  reuse             (boolean)


AJP13_GET_BODY_CHUNK :=
  prefix_code       6
  requested_length  (integer)

Send Headers

状态代码和消息是通常的请求状态的描述(例如“200”和“OK”). 响应头的编码格式和请求头类似,映射关系如下:

Name Code value
Content-Type 0xA001
Content-Language 0xA002
Content-Length 0xA003
Date 0xA004
Last-Modified 0xA005
Location 0xA006
Set-Cookie 0xA007
Set-Cookie2 0xA008
Servlet-Engine 0xA009
Status 0xA00A
WWW-Authenticate 0xA00B

End Response

该消息标志着响应的终止,如果reuse=0,标志着连接发生错误,将关闭连接,正常情况reuse=1,标志连接正常,可重用.

Get Body Chunk

该数据包用于向服务端获取更多的请求体数据,请求体数据使用数据包code为3的Send Body Chunk类型数据作为响应.



AJP