当前位置: 首页 > 文档资料 > Swoole 中文文档 >

Http\Server

优质
小牛编辑
141浏览
2023-12-01

?> Http\ServerHttp协议的支持并不完整,一定要作为应用服务器处理动态请求。并且在前端增加Nginx作为代理

?> Http\Server继承自Server,所以Server提供的所有API和配置项都可以使用,进程模型也是一致的。请参考Server章节。

内置Http服务器的支持,通过几行代码即可写出一个高并发,高性能,异步IO的多进程Http服务器。

$http = new Swoole\Http\Server("127.0.0.1", 9501);
$http->on('request', function ($request, $response) {
    $response->end("<h1>Hello Swoole. #".rand(1000, 9999)."</h1>");
});
$http->start();

通过使用Apache bench工具进行压力测试,在Inter Core-I5 4核 + 8G内存的普通PC机器上,Http\Server可以达到近11万QPS。远远超过PHP-FPMGolangNode.js自带Http服务器。性能几乎接近与Nginx的静态文件处理。

ab -c 200 -n 200000 -k http://127.0.0.1:9501/
  • 使用 Http2 协议

    • 使用SSL下的Http2协议必须安装openssl, 且需要高版本openssl必须支持TLS1.2ALPNNPN
    • 编译时需要使用--enable-http2开启
./configure --enable-openssl --enable-http2

设置Http服务器的open_http2_protocoltrue

$server = new Swoole\Http\Server("127.0.0.1", 9501, SWOOLE_PROCESS, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$server->set([
    'ssl_cert_file' => $ssl_dir . '/ssl.crt',
    'ssl_key_file' => $ssl_dir . '/ssl.key',
    'open_http2_protocol' => true,
]);
  • nginx+swoole配置
server {
    root /data/wwwroot/;
    server_name local.swoole.com;

    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "keep-alive";
        proxy_set_header X-Real-IP $remote_addr;
        if (!-e $request_filename) {
             proxy_pass http://127.0.0.1:9501;
        }
    }
}

?> 通过读取$request->header['x-real-ip']来获取客户端的真实IP

on()

?> 注册事件回调函数。

?> 与 Server的回调 相同,不同之处是:

  • Http\Server->on不接受onConnect/onReceive回调设置

  • Http\Server->on额外接受1种新的事件类型onRequest

  • onRequest事件

$http_server->on('request', function(swoole_http_request $request, swoole_http_response $response) {
     $response->end("<h1>hello swoole</h1>");
})

在收到一个完整的Http请求后,会回调此函数。回调函数共有2个参数:

  • $requestHttp请求信息对象,包含了header/get/post/cookie等相关信息
  • $responseHttp响应对象,支持cookie/header/statusHttp操作
  • onRequest回调函数返回时底层会销毁$request$response对象

start()

?> 启动Http服务器

?> 启动后开始监听端口,并接收新的HttpWebSocket请求。

Swoole\Http\Server->start();

Http\Request

Http请求对象,保存了Http客户端请求的相关信息,包括GETPOSTCOOKIEHeader等。

!> 请勿使用&符号引用Http\Request对象

header

?> Http请求的头部信息。类型为数组,所有key均为小写。

Swoole\Http\Request->header: array;
  • 示例
echo $request->header['host'];
echo $request->header['accept-language'];

server

?> Http请求相关的服务器信息。

?> 相当于PHP$_SERVER数组。包含了Http请求的方法,URL路径,客户端IP等信息。

Swoole\Http\Request->server: array;

数组的key全部为小写,并且与PHP$_SERVER数组保持一致

  • 示例
echo $request->server['request_time'];
key说明
query_string请求的 GET 参数,如:id=1&cid=2 如果没有 GET 参数,该项不存在
request_method请求方法,GET/POST
request_uriGET 参数的访问地址,如/favicon.ico
path_inforequest_uri
request_timerequest_time是在Worker设置的,在SWOOLE_PROCESS模式下存在dispatch过程,因此可能会与实际收包时间存在偏差。尤其是当请求量超过服务器处理能力时,request_time可能远滞后于实际收包时间。可以通过$server->getClientInfo方法获取last_time获得准确的收包时间。
request_time_float请求开始的时间戳,以微秒为单位,float类型,如1576220199.2725
server_protocol服务器协议版本号,Http 是:HTTP/1.0HTTP/1.1Http2 是:HTTP/2
server_port服务器监听的端口
remote_port客户端的端口
remote_addr客户端的 IP 地址
master_time连接上次通讯时间

get

?> Http请求的GET参数,相当于PHP中的$_GET,格式为数组。

Swoole\Http\Request->get: array;
  • 示例
// 如:index.php?hello=123
echo $request->get['hello'];
// 获取所有GET参数
var_dump($request->get);
  • 注意

!> 为防止HASH攻击,GET参数最大不允许超过128

post

?> HTTP POST参数,格式为数组

Swoole\Http\Request->post: array;
  • 示例
echo $request->post['hello'];
  • 注意

!> -POSTHeader加起来的尺寸不得超过package_max_length的设置,否则会认为是恶意请求
-POST参数的个数最大不超过128

cookie

?> HTTP请求携带的COOKIE信息,格式为键值对数组。

Swoole\Http\Request->cookie: array;
  • 示例
echo $request->cookie['username'];

files

?> 上传文件信息。

?> 类型为以form名称为key的二维数组。与PHP$_FILES相同。最大文件尺寸不得超过package_max_length设置的值。请勿使用Swoole\Http\Server处理大文件上传。

Swoole\Http\Request->files: array;
  • 示例
Array
(
    [name] => facepalm.jpg // 浏览器上传时传入的文件名称
    [type] => image/jpeg // MIME类型
    [tmp_name] => /tmp/swoole.upfile.n3FmFr // 上传的临时文件,文件名以/tmp/swoole.upfile开头
    [size] => 15476 // 文件尺寸
    [error] => 0
)
  • 注意

!> 当$request对象销毁时,会自动删除上传的临时文件

rawContent()

?> 获取原始的POST包体。

?> 用于非application/x-www-form-urlencoded格式的Http POST请求。返回原始POST数据,此函数等同于PHPfopen('php://input')

Swoole\Http\Request->rawContent(): string;
  • 提示

    • 有些情况下服务器不需要解析Http POST请求参数,通过http_parse_post 配置,可以关闭POST数据解析。

getData()

?> 获取完整的原始Http请求报文。包括Http HeaderHttp Body

Swoole\Http\Request->getData(): string;

Http\Response

Http响应对象,通过调用此对象的方法,实现Http响应发送。

?> 当Response对象销毁时,如果未调用end发送Http响应,底层会自动执行end("");

!> 请勿使用&符号引用Http\Response对象

header()

?> 设置HTTP响应的Header信息

Swoole\Http\Response->header(string $key, string $value, bool $ucwords = true);
  • 参数

    • string $key

      • 功能Http头的Key
      • 默认值:无
      • 其它值:无
    • string $value

      • 功能Http头的value
      • 默认值:无
      • 其它值:无
    • string $ucwords

      • 功能: 是否需要对Key进行Http约定格式化【默认true会自动格式化】
      • 默认值true
      • 其它值:无
  • 返回值

    • 设置失败,返回false
    • 设置成功,没有任何返回值
  • 注意

    -header设置必须在end方法之前 -$key必须完全符合Http的约定,每个单词首字母大写,不得包含中文,下划线或者其他特殊字符
    -$value必须填写
    -$ucwords 设为 true,底层会自动对$key进行约定格式化

    • 重复设置相同$keyHttp头会覆盖,取最后一次。
  • 示例

$response->header('content-type', 'image/jpeg', true);

trailer()

?> Header信息附加到HTTP响应的末尾,仅在HTTP2中可用,用于消息完整性检查,数字签名等。

Swoole\Http\Response->trailer(string $key, string $value, bool $ucwords = true);
  • 参数

    • string $key

      • 功能Http头的Key
      • 默认值:无
      • 其它值:无
    • string $value

      • 功能Http头的value
      • 默认值:无
      • 其它值:无
    • string $ucwords

      • 功能: 是否需要对Key进行Http约定格式化【默认true会自动格式化】
      • 默认值true
      • 其它值:无
  • 返回值

    • 设置失败,返回false
    • 设置成功,没有任何返回值
  • 注意

    • 重复设置相同$keyHttp头会覆盖,取最后一次。
  • 示例

$response->trailer('grpc-status', 0);
$response->trailer('grpc-message', '');

cookie()

?> 设置HTTP响应的cookie信息。此方法参数与PHPsetcookie完全一致。

Swoole\Http\Response->cookie(string $key, string $value = '', int $expire = 0 , string $path = '/', string $domain  = '', bool $secure = false , bool $httponly = false, string $samesite = '');
  • 注意

    !> -cookie设置必须在end方法之前
    -$samesite 参数从 v4.4.6 版本开始支持
    -Swoole会自动会对$value进行urlencode编码,可使用rawCookie()方法关闭对$value的编码处理
    -Swoole允许设置多个相同$keyCOOKIE

rawCookie()

?> 设置HTTP响应的cookie信息

!> rawCookie()的参数和上文的cookie()一致,只不过不进行编码处理

status()

?> 发送Http状态码。

Swoole\Http\Response->status(int $http_status_code, int $reason): bool;
  • 参数

    • int $http_status_code

      • 功能: 设置 HttpCode
      • 默认值200
      • 其它值:无
    • int $reason

      • 功能: 可设置任意 HttpCode
      • 默认值:无
      • 其它值:无
  • 提示

    • 如果只传入了第一个参数 $http_status_code必须为合法的HttpCode,如200502301404等,否则会设置为200状态码
    • 如果设置了第二个参数$reason$http_status_code可以为任意的数值,包括未定义的HttpCode,如499
    • 必须在 $response->end() 之前执行status方法

gzip()

!> 此方法在4.1.0或更高版本中已废弃, 请移步http_compression;在新版本中使用http_compression配置项取代了gzip方法。
主要原因是gzip()方法未判断浏览器客户端传入的Accept-Encoding头,如果客户端不支持gzip压缩,强行使用会导致客户端无法解压。
全新的http_compression配置项会根据客户端Accept-Encoding头,自动选择是否压缩,并自动选择最佳的压缩算法。

?> 启用Http GZIP压缩。压缩可以减小HTML内容的尺寸,有效节省网络带宽,提高响应时间。必须在write/end发送内容之前执行gzip,否则会抛出错误。

Swoole\Http\Response->gzip(int $level = 1);
  • 参数

    • int $level
      • 功能:压缩等级,等级越高压缩后的尺寸越小,但CPU消耗更多。
      • 默认值:1
      • 其它值1-9

!> 调用gzip方法后,底层会自动添加Http编码头,PHP代码中不应当再行设置相关Http头;jpg/png/gif格式的图片已经经过压缩,无需再次压缩

!> gzip功能依赖zlib库,在编译swoole时底层会检测系统是否存在zlib,如果不存在,gzip方法将不可用。可以使用yumapt-get安装zlib库:

   sudo apt-get install libz-dev

redirect()

?> 发送Http跳转。调用此方法会自动end发送并结束响应。

Swoole\Http\Response->redirect(string $url, int $http_code = 302): void;
  • 参数

    • string $url

      • 功能:跳转的新地址,作为Location头进行发送
      • 默认值:无
      • 其它值:无
    • int $http_code

      • 功能:状态码【默认为302临时跳转,传入301表示永久跳转】
      • 默认值302
      • 其它值:无
  • 示例

    $http = new Swoole\Http\Server("0.0.0.0", 9501, SWOOLE_BASE);
    
    $http->on('request', function ($req, Swoole\Http\Response $resp) {
        $resp->redirect("http://www.baidu.com/", 301);
    });
    
    $http->start();

write()

?> 启用Http Chunk分段向浏览器发送相应内容。

?> 关于Http Chunk可以参考Http协议标准文档。

Swoole\Http\Response->write(string $data): bool;
  • 参数

    • string $data
      • 功能:要发送的数据内容【最大长度不得超过2M,受buffer_output_size配置项控制】
      • 默认值:无
      • 其它值:无
  • 提示

    • 使用write分段发送数据后,end方法将不接受任何参数,调用end只是会发送一个长度为0Chunk表示数据传输完毕。

sendfile()

?> 发送文件到浏览器。

Swoole\Http\Response->sendfile(string $filename, int $offset = 0, int $length = 0): bool;
  • 参数

    • string $filename

      • 功能:要发送的文件名称【文件不存在或没有访问权限sendfile会失败】
      • 默认值:无
      • 其它值:无
    • int $offset

      • 功能:上传文件的偏移量【可以指定从文件的中间部分开始传输数据。此特性可用于支持断点续传】
      • 默认值0
      • 其它值:无
    • int $length

      • 功能:发送数据的尺寸
      • 默认值:文件的尺寸
      • 其它值:无
  • 提示

    • 底层无法推断要发送文件的MIME格式因此需要应用代码指定Content-Type
    • 调用sendfile前不得使用write方法发送Http-Chunk
    • 调用sendfile后底层会自动执行end
    • sendfile不支持gzip压缩
  • 示例

    $response->header('Content-Type', 'image/jpeg');
    $response->sendfile(__DIR__.$request->server['request_uri']);

end()

?> 发送Http响应体,并结束请求处理。

Swoole\Http\Response->end(string $html): bool;
  • 参数

    • string $html
      • 功能:要发送的内容
      • 默认值:无
      • 其它值:无
  • 提示

    • end只能调用一次,如果需要分多次向客户端发送数据,请使用write方法
    • 客户端开启了KeepAlive,连接将会保持,服务器会等待下一次请求
    • 客户端未开启KeepAlive,服务器将会切断连接

detach()

?> 分离响应对象。使用此方法后,$response对象销毁时不会自动end,与 Http\Response::createServer::send 配合使用。

!> detach方法只能在 SWOOLE_PROCESS 模式下使用。

Swoole\Http\Response->detach(): bool;
  • 示例

    • 跨进程响应

    ?> 某些情况下,需要在 Task进程中对客户端发出响应。这时可以利用detach使$response对象独立。在 Task进程可以重新构建$response,发起Http请求响应。

    $http = new Swoole\Http\Server("0.0.0.0", 9501);
    
    $http->set(['task_worker_num' => 1, 'worker_num' => 1]);
    
    $http->on('request', function ($req, Swoole\Http\Response $resp) use ($http) {
        $resp->detach();
        $http->task(strval($resp->fd));
    });
    
    $http->on('finish', function () {
        echo "task finish";
    });
    
    $http->on('task', function ($serv, $task_id, $worker_id, $data) {
        var_dump($data);
        $resp = Swoole\Http\Response::create($data);
        $resp->end("in task");
        echo "async task\n";
    });
    
    $http->start();
    • 发送任意内容

    ?> 某些特殊的场景下,需要对客户端发送特殊的响应内容。Http\Response对象自带的end方法无法满足需求,可以使用detach分离响应对象,然后自行组装HTTP协议响应数据,并使用Server::send发送数据。

    $http = new Swoole\Http\Server("0.0.0.0", 9501);
    
    $http->on('request', function ($req, Swoole\Http\Response $resp) use ($http) {
        $resp->detach();
        $http->send($resp->fd, "HTTP/1.1 200 OK\r\nServer: server\r\n\r\nHello World\n");
    });
    
    $http->start();

create()

?> 构造新的Swoole\Http\Response对象。

!> 使用此方法前请务必调用detach方法将旧的$response对象分离,否则可能会造成对同一个请求发送两次响应内容。

Swoole\Http\Response::create(int $fd): Swoole\Http\Response;

!> 调用成功返回一个新的Http\Response对象,调用失败返回false

  • 参数

    • int $fd
      • 功能:参数为需要绑定的连接$fd【调用Http\Response对象的endwrite方法时会向此连接发送数据】
      • 默认值:无
      • 其它值:无
  • 示例

    $http = new Swoole\Http\Server("0.0.0.0", 9501);
    
    $http->on('request', function ($req, Swoole\Http\Response $resp) use ($http) {
        $resp->detach();
        $resp2 = Swoole\Http\Response::create($req->fd);
        $resp2->end("hello world");
    });
    
    $http->start();

配置选项

upload_tmp_dir

?> 设置上传文件的临时目录。目录最大长度不得超过220字节

$server->set(array(
    'upload_tmp_dir' => '/data/uploadfiles/',
));

http_parse_post

?> 针对Request对象的配置,设置POST消息解析开关,默认开启

  • 设置为true时自动将Content-Type为x-www-form-urlencoded的请求包体解析到POST数组。
  • 设置为false时将关闭POST解析。
$server->set(array(
    'http_parse_post' => false,
));

http_parse_cookie

?> 针对Request对象的配置,关闭Cookie解析,将在header中保留未经处理的原始的Cookies信息。默认开启

$server->set(array(
    'http_parse_cookie' => false,
));

http_compression

?> 针对Response对象的配置,启用压缩。默认为开启。

!> - http-chunk不支持分段单独压缩, 若使用write方法, 将会强制关闭压缩。
-http_compressionv4.1.0或更高版本可用

$server->set(array(
    'http_compression' => false,
));

目前支持gzipbrdeflate 三种压缩格式,底层会根据浏览器客户端传入的Accept-Encoding头自动选择压缩方式。

依赖:

gzipdeflate依赖zlib库,在编译Swoole时底层会检测系统是否存在zlib

可以使用yumapt-get安装zlib库:

sudo apt-get install libz-dev

br压缩格式依赖googlebrotli库,安装方式请自行搜索install brotli on linux,在编译Swoole时底层会检测系统是否存在brotli

http_compression_level

?> 压缩级别,针对Response对象的配置

!> $level 压缩等级,范围是1-9,等级越高压缩后的尺寸越小,但CPU消耗更多。默认为1, 最高为9

document_root

?> 配置静态文件根目录,与enable_static_handler配合使用。

!> 此功能较为简易, 请勿在公网环境直接使用

$server->set([
    'document_root' => '/data/webroot/example.com', // v4.4.0以下版本, 此处必须为绝对路径
    'enable_static_handler' => true,
]);
  • 设置document_root并设置enable_static_handlertrue后,底层收到Http请求会先判断document_root路径下是否存在此文件,如果存在会直接发送文件内容给客户端,不再触发onRequest回调。
  • 使用静态文件处理特性时,应当将动态PHP代码和静态文件进行隔离,静态文件存放到特定的目录

enable_static_handler

开启静态文件请求处理功能, 需配合document_root使用 默认false

static_handler_locations

?> 设置静态处理器的路径。类型为数组,默认不启用。

!> Swoole >= v4.4.0

$server->set([
    "static_handler_locations" => ['/static', '/app/images'],
]);
  • 类似于Nginxlocation指令,可以指定一个或多个路径为静态路径。只有URL在指定路径下才会启用静态文件处理器,否则会视为动态请求。
  • location项必须以/开头
  • 支持多级路径,如/app/images
  • 启用static_handler_locations后,如果请求对应的文件不存在,将直接返回404错误

open_http2_protocol

?> 启用HTTP2协议解析【默认值:false