在很久以前,php程序员需要向其他服务器发起一个HTTP请求时,通常使用CURL扩展功能,随着时代发展,出现了更加高级的专用库GuzzleHttp,它让我们可以写更少的代码,做更多的事情,在底层的传输上,不但可以用CURL,还可以用PHP流,或者自定义发送方式。
官网文档:
https://guzzle-cn.readthedocs.io/zh_CN/latest/#
https://docs.guzzlephp.org/en/stable/
关于该库的安装和使用详见以上网址,GuzzleHttp使用处理器和中间件系统去发送HTTP请求,这里仅对这两重要概念做下解释:
处理器handler:
用于处理请求的发送和响应的接收
中间件middleware:
增强处理器的功能,在发送请求和接收响应期间,参与一些额外处理,有点类似Drupal的钩子,比如修改查询参数、添加响应头等等。举个例子:我们在开发微信支付接口的时候,腾讯公司提供的SDK就是一个GuzzleHttp库的中间件。
在Drupal中有4个和GuzzleHttp库相关的服务,分别如下。
HTTP客户端服务:
服务id:http_client
定义如下:
http_client:
class: GuzzleHttp\Client
factory: ['@http_client_factory', 'fromOptions']
用于向其他服务器发起HTTP请求,由定义可见该服务内部是由工厂实例化的,使用示例如下:
$client = \Drupal::httpClient();
$response = $client->get('http://www.baidu.com');
$body = $response->getBody();
print_r((string)$body);die;
在这个列子中我们就将百度的页面展示出来了
HTTP客户端工厂服务:
定义如下:
http_client_factory:
class: Drupal\Core\Http\ClientFactory
arguments: ['@http_handler_stack']
用于通过一些选项去实例化HTTP客户端对象,从该服务可以看出我们可以在全局配置文件中,使用以下配置项:
“http_client_config”
去覆写一些默认的HTTP客户端对象所需的默认选项,详见以下:
\Drupal\Core\Http\ClientFactory::fromOptions
HTTP处理器堆栈服务:
定义如下:
http_handler_stack:
class: GuzzleHttp\HandlerStack
public: false
factory: GuzzleHttp\HandlerStack::create
configurator: ['@http_handler_stack_configurator', configure]
用于创建HTTP处理器堆栈,这里服务定义中的“configurator”项是Symfony框架中新增的服务配置器,服务配置器是服务容器的一个特性,它可让你在服务实例化后用一个回调对象来对服务做一些配置,换句话说是在服务实例化后,会被首先传递到其定义的配置器中进行配置,这里是http_handler_stack_configurator服务的configure方法,关于服务配置器详见:
https://symfony.com/doc/current/service_container/configurators.html
HTTP处理器堆栈配置器:
定义如下:
http_handler_stack_configurator:
class: Drupal\Core\Http\HandlerStackConfigurator
public: false
arguments: ['@service_container']
这是个服务配置器服务,用来配置HTTP处理器堆栈服务,她会收集具备如下服务标签的服务(HTTP客户端中间件服务):
“http_client_middleware”
并将这些服务作为GuzzleHttp库的HTTP中间件压入HTTP处理器堆栈,容器编译器如下:
Drupal\Core\DependencyInjection\Compiler\GuzzleMiddlewarePass
在Drupal系统中默认没有定义HTTP客户端中间件服务,而GuzzleHttp库原生自带了4个中间件(这4个中间件都和对应的选项设置有关系,如果没有它们,则对应选项会失效):
http_errors:当状态码大于等于400时,进行异常抛出处理
allow_redirects:重定向相关处理
cookies:cookie处理
prepare_body:预处理body,如根据长短和类型设置默认的请求头等
详见:
\GuzzleHttp\HandlerStack::create
HTTP客户端常见用法示例:
示例一:提交json数据
$data = [
'a' => 'yunke',
'b' => 100,
1 => 'drupal',
];
$client = \Drupal::httpClient();
$clientURL = 'http://www.dp9.com/yunke-app/test-1';
$HTTPOptions = [
'json' => $data,
'headers' => ['Accept' => 'application/json'],
];
$responseData = [];
try {
$response = $client->post($clientURL, $HTTPOptions);
$responseData = $response->getBody()->getContents();
} catch (RequestException $e) {
//HTTP状态码大于等于400 或者网络错误将报错触发这里
$msg = $e->getMessage() . "\n";
if ($e->hasResponse()) {
$msg .= "请求失败,响应状态码:" . $e->getResponse()->getStatusCode();
$msg .= "响应body:" . $e->getResponse()->getBody() . "\n";
}
echo $msg;
}
示例二:以表单方式提交数据
同上,只是选项改为如下即可:
$HTTPOptions = [
'form_params' => $data,
];
示例三:以GET方式提交查询参数:
同上,只是选项改为如下即可:
$HTTPOptions = [
'query' => $data,
];
示例四:上传文件:
同上,只是选项改为如下即可:
$HTTPOptions = [
'multipart' => [
[
'name' => 'field_name',
'contents' => 'abc',
],
[
'name' => 'file_name',
'contents' => Psr7\Utils::tryFopen('/path/to/file', 'r'),
],
[
'name' => 'other_file',
'contents' => 'hello',
'filename' => 'filename.txt',
'headers' => [
'X-Foo' => 'this is an extra header to include',
],
],
],
];
示例五:发送cookie数据
同上,只是选项改为如下即可:
$cookies = ['name' => 'yunke'];
$jar = \GuzzleHttp\Cookie\CookieJar::fromArray($cookies,'www.dp9.com');
$HTTPOptions = [
'cookies' => $jar,
];