forked from PlumpMath/php-flame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhttp.php
419 lines (415 loc) · 12.9 KB
/
http.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
<?php
/**
* 提供基本的 HTTP(S) 客户端、服务端封装;服务端仅支持 HTTP/1.1 协议; 客户端支持 (TLS) HTTP/1.x HTTP/2 协议;
* 注意:
* * 默认状态,服务器对客户端请求连接进行 KeepAlive 复用(长连状态);若需要使用短连接,请自行制定 Connection: close 头(短连状态);
* * 当进程接收到 SIGUSR1 信号时,切换连接复用状态(短连状态附加 Connection: close 头信息);
*/
namespace flame\http;
/**
* 使用默认客户端, 执行请求
*/
function exec(client_request $req): client_response {
return new client_response();
}
/**
* 使用默认客户端, 构建并执行一个 GET 请求
*/
function get(string $url, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 使用默认客户端, 构建并执行一个 POST 请求
*/
function post(string $url, $data, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 使用默认客户端, 构建并执行一个 PUT 请求
*/
function put(string $url, $data, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 使用默认客户端, 构建并执行一个 DELETE 请求
*/
function delete(string $url, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 客户端,用于执行请求
*/
class client {
/**
* 构建新的客户端对象
* @param array $options 选项, 目前支持的选项如下:
* * "connection_per_host" - 单个 HOST 目标连接限制, 默认 16,超出限制时须等待;
*/
function __construct(array $options = []) {}
/**
* 执行请求, 返回响应
*/
function exec(client_request $req): client_response {
return new client_response();
}
/**
* 构建并执行一个 GET 请求
*/
function get(string $url, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 构建并执行一个 POST 请求
*/
function post(string $url, $data, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 构建并执行一个 PUT 请求
*/
function put(string $url, $data, int $timeout = 3000): client_response {
return new client_response();
}
/**
* 构建并执行一个 DELETE 请求
*/
function delete(string $url, int $timeout = 3000): client_response {
return new client_response();
}
}
/**
* 客户端请求对象,用于拼装生成一个客户端请求(待执行)
*/
class client_request {
/**
* 由框架自行选择版本
*/
const HTTP_VERSION_NONE = 0;
/**
* 强制使用 HTTP/1.0 协议
*/
const HTTP_VERSION_1_0 = 1;
/**
* 强制使用 HTTP/1.1 协议
*/
const HTTP_VERSION_1_1 = 2;
/**
* 尝试使用 HTTP/2 协议,自动退回 HTTP/1.1 版本
*/
const HTTP_VERSION_2 = 3;
/**
* 尝试在 TLS (HTTPS) 使用 HTTP/2 协议,自动退化 HTTP/1.1 版本
*/
const HTTP_VERSION_2_TLS = 4;
/**
* 强制在 non-TLS 状态进行 HTTP/2 请求,TLS (HTTPS) 时同 HTTP_VERSION_2_TLS
*/
const HTTP_VERSION_2_PRI = 5;
const SSL_VERIFY_NONE = 0;
/**
* 验证对端证书
*/
const SSL_VERIFY_PEER = 1;
/**
* 验证证书域名
*/
const SSL_VERIFY_HOST = 2;
/*
* 验证证书状态
*/
const SSL_VERIFY_STATUS = 4;
/**
* 相当于 SSL_VERIFY_PEER | SSL_VERIFY_HOST | SSL_VERIFY_STATUS
*/
const SSL_VERIFY_ALL = 7;
/**
* @var int
*/
public $timeout;
/**
* @var string
*/
public $method;
/**
* @var string
*/
public $url;
/**
* 请求头;可通过指定 "Connection" => "close" 防止连接复用;
* @var array
*/
public $header;
/**
* @var array
*/
public $cookie;
/**
* @var mixed
*/
public $body;
/**
* 构建请求, 可选的指定请求体 `$body` (将自动设置为 POST 请求方法)及超时时间 `$timeout`
*/
function __construct(string $url, $body = null, int $timeout = 3000) {}
/**
* @param string $cert_file 证书文件路径
* @param string $pkey_file 密钥文件路径
* @param string $pkey_pass 密钥密码
*/
function ssl_pem(string $cert_file, string $pkey_file = "", string $pkey_pass = "") {}
/**
* 请使用 client_request::SSL_VERIFY_* 相关常量进行设置(可按位组合)
*/
function ssl_verify(int $verify) {}
/**
* 请选择使用 client_request::HTTP_VERSION_* 常量设置版本
*/
function http_version(int $version) {}
}
/**
* 客户端响应对象,执行请求后得到
*/
class client_response {
/**
* 对应请求实际的 HTTP 版本
* @var string
*/
public $version;
/**
* 响应码
* @var int
*/
public $status;
/**
* 注意: 目前使用了数组形式, 切暂不支持多个同名 Header 数据的访问;
* @var array
*/
public $header;
/**
* @var mixed 以下几种 Content-Type 将自动进行解析并生成关联数组:
* * "application/json"
* * "application/x-www-form-urlencoded"
* * "multipart/form-data"
* 其他类型保持文本的原始数据(与 $raw_body 相同);
*/
public $body;
/**
* 原始请求体数据
* @var string
*/
public $raw_body;
}
/**
* HTTP 服务器
*/
class server {
/**
* 服务端本地监听地址
*/
public $address;
/**
* 创建服务器并绑定地址
*/
function __construct(string $address) {}
/**
* 每次 HTTP 请求在执行对应 path 的处理器前, 先执行下述设置的回调;
* 回调形式如下:
* function callback(server_request $req, server_response $res, bool $match) {}
* 其中 $match 参数标识此请求是否匹配了定义的 path 处理器;
* 当 callback 函数返回 false 时, 将**不再**执行后续处理器
*/
function before(callable $cb):server {
return $this;
}
/**
* 每次 HTTP 请求在执行对应 path 处理器后, 会执行下述设置的回调;
* 回调形式同 before();
* 注意: 若 before 回调或 path 回调返回了 false, 此 after 回调将不再执行;
*/
function after(callable $cb):server {
return $this;
}
/**
* 设置一个处理 "PUT $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function put(string $path, callable $cb):server {
return $this;
}
/**
* 设置一个处理 "DELETE $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function delete(string $path, callable $cb):server {
return $this;
}
/**
* 设置一个处理 "POST $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function post(string $path, callable $cb):server {
return $this;
}
/**
* 设置一个处理 "PATCH $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function patch(string $path, callable $cb):server {
return $this;
}
/**
* 设置一个处理 "GET $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function get(string $path, callable $cb):server {
return $this;
}
/**
* 设置一个处理 "HEAD $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function head(string $path, callable $cb):server {
return $this;
}
/**
* 设置一个处理 "OPTIONS $path HTTP/1.1" 请求的路径 path 处理器;
* 注意: 当 before 回调返回 false 时, 此处理器将不再被执行;
*/
function options(string $path, callable $cb):server {
return $this;
}
/**
* 启动服务器, 监听请求并执行对应回调
* 注意: 运行服务器将阻塞当前协程;
*/
function run() {}
/**
* 停止服务器, 不再接收新的连接; 上述 run() 阻塞协程将恢复执行;
* 注意: 正在处理中的请求不收影响(继续处理);
*/
function close() {}
}
/**
* 服务端请求对象(由 server 对应回调获得)
*/
class server_request {
/**
* 请求方法(大写)
* @var string
*/
public $method = "GET";
/**
* 请求路径(不包含查询参数)
* @var string
*/
public $path = "/";
/**
* 请求参数, 使用 PHP 内置 parse_str() 函数解析得到;
* @var array
*/
public $query;
/**
* 请求头;
* @var array
* 注意:所有头信息字段名被转换为**小写**形式;
* 注意:由于目前使用数组形式,暂不支持同名字段;
*/
public $header;
/**
* 请求 Cookie
* @var array
*/
public $cookie;
/**
* 请求体, 以下几种 Content-Type 时自动解析为关联数组:
* * "application/json"
* * "application/x-www-form-urlencoded"
* * "multipart/form-data"
* 其他类��时与 $raw_body 相同;
* @var mixed
*/
public $body;
/**
* 原始请求体
* @var string
*/
public $raw_body;
/**
* 上传文件,形如:
* [
* "file_field_1"=>
* [
* "content-type" => "mime_type",
* ... // other header field lowercased if available
* "filename" => "original_file_name",
* "size" => file_data_size,
* "data" => "file_data", // content of the uploaded file
* ],
* "file_filed_2"=>
* ...
* ]
* 若无上传文件时可能为空
* @var array
*/
public $file;
/**
* 用户可设置的请求关联数据;
* @example 在 before 回调中从 Cookie 中提取用户信息放在 $req->data["user"] 中, 后续处理器即可访问 $req->data["user"] 获取户信息;
* @var array
*/
public $data;
}
/**
* 服务端响应对象(由 server 对应处理回调获得)提供接口向客户端返回数据
* 默认状态下 HTTP/1.1 使用 长连接(保持连接);可使用 Connection: close 头禁止;
* 向进程发送 SIGUSR1 信号时将会在 长短连 状态切换(短连接状态自动附加 Connection: close 头信息);
*/
class server_response {
/**
* 响应状态码, 可以直接设置; 也可以在 Transfer-Encoding: chunked 模式时使用 write_header 指定;
* @var int
*/
public $status = 200;
/**
* 响应头信息, Key/Val 形式
* @var array
* 注意:一般情况下 Key/Val 均为字符串,其他类型会被转换为字符串输出;
*/
public $header;
// public $cookie;
/**
* 响应体, 用于在 Content-Length: xxx 响应模式下返回数据;
* @var mixed ��意数据, 实际响应会序列化此数据; 以下几种 Content-Type 存在内置的序列化:
* * "application/json" - 使用 json_encode 进行序列化;
* * "application/x-www-form-urlencoded" - 使用 http_build_query 进行序列化;
* 其他类型强制转换为文本类型后返回响应;
*/
public $body;
/**
* 设置返回的 Set-Cookie 项;
* 参数功能与 PHP 内置 set_cookie 函数类似;
*/
function set_cookie(string $name, string $value = null, int $expire = 0, string $path = "/", string $domain = "", bool $secure = false, bool $http_only = false) {}
/**
* 返回响应头, 用于启用 Transfer-Encoding: chunked 模式, 准备持续响应数据;
* @param int $status 当参数存在时, 覆盖上述 $res->status 属性响应码;
*
* Transfer-Encoding: chunked 模式可用于 EventSource 等持续响应;
*/
function write_header($status = 0) {}
/**
* 在 Transfer-Encoding: chunked 模式下, 返回一个 chunk 数据块;
*/
function write(string $chunk) {}
/**
* 在 Transfer-Encoding: chunked 模式下, 结束响应过程 (返回最后一个结束块);
* @param string $chunk 可选, 调用上述 write() 返回一个数据块;
*/
function end(string $chunk = null) {}
/**
* 响应一个文件的内容; 一般需要自行设置对应文件的 Content-Type 以保证浏览器能正常渲染;
* 下述参数中的 $path 将会被正常化处理, 以保证其不超出 $root 指定的根目录范围;
* 注意: 此功能一般仅用于调试或少量文件访问使用, 大量生产环境请考虑使用 nginx 等代为处理静态文件;
*/
function file(string $root, string $path) {}
}