正文
你可能习惯了在项目中自己封装Curl族函数实现请求,可以尝试使用下封装好的 guzzlehttp/guzzle 包。
Guzzle 是一个 PHP HTTP 客户端,可以轻松发送 HTTP 请求并轻松与 Web 服务集成。
用于构建查询字符串、POST 请求、流式传输大型上传、流式传输大型下载、使用 HTTP cookie、上传 JSON 数据等的简单界面…
可以使用相同的接口发送同步和异步请求。
对请求、响应和流使用 PSR-7 接口。 这允许您在 Guzzle 中使用其他 PSR-7 兼容库。
支持 PSR-18 允许其他 PSR-18 HTTP 客户端之间的互操作性。
抽象出底层 HTTP 传输,允许您编写与环境和传输无关的代码; 即,对 cURL、PHP 流、sockets或非阻塞事件循环没有硬依赖。
中间件系统允许您增强和组合客户端行为。
安装
guzzlehttp/guzzle
包现在的版本到了 7.4.x 版,项目安装 guzzlehttp/guzzle
,指定版本,不然安装的是dev版:
composer require guzzlehttp/guzzle 7.4.1
root@02891538d8c9:/var/www/html/test# composer require guzzlehttp/guzzle 7.4.1
The "fxp/composer-asset-plugin" plugin (installed globally) was skipped because it requires a Plugin API version ("^1.0") that does not match your Composer installation ("2.3.0"). You may need to run composer update with the "--no-plugins" option.
./composer.json has been updated
The "fxp/composer-asset-plugin" plugin (installed globally) was skipped because it requires a Plugin API version ("^1.0") that does not match your Composer installation ("2.3.0"). You may need to run composer update with the "--no-plugins" option.
Running composer update guzzlehttp/guzzle
Loading composer repositories with package information
Updating dependencies
Lock file operations: 8 installs, 0 updates, 0 removals
- Locking guzzlehttp/guzzle (7.4.1)
- Locking guzzlehttp/promises (dev-master fe752ae)
- Locking guzzlehttp/psr7 (dev-master f8ae7cb)
- Locking psr/http-client (dev-master 22b2ef5)
- Locking psr/http-factory (dev-master 36fa03d)
- Locking psr/http-message (dev-master efd67d1)
- Locking ralouphie/getallheaders (3.0.3)
- Locking symfony/deprecation-contracts (2.5.x-dev e8b495e)
Writing lock file
Installing dependencies from lock file (including require-dev)
Package operations: 8 installs, 0 updates, 0 removals
- Installing symfony/deprecation-contracts (2.5.x-dev e8b495e): Extracting archive
- Installing psr/http-message (dev-master efd67d1): Extracting archive
- Installing psr/http-client (dev-master 22b2ef5): Extracting archive
- Installing ralouphie/getallheaders (3.0.3): Extracting archive
- Installing psr/http-factory (dev-master 36fa03d): Extracting archive
- Installing guzzlehttp/psr7 (dev-master f8ae7cb): Extracting archive
- Installing guzzlehttp/promises (dev-master fe752ae): Extracting archive
- Installing guzzlehttp/guzzle (7.4.1): Extracting archive
3 package suggestions were added by new dependencies, use `composer suggest` to see details.
Generating autoload files
4 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
root@02891538d8c9:/var/www/html/test#
创建客户端
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'http://httpbin.org',
// You can set any number of default request options.
'timeout' => 2.0,
]);
同步请求
$response = $client->request('GET', 'ip'); // http://httpbin.org/ip
$response = $client->get('http://httpbin.org/get');
$response = $client->delete('http://httpbin.org/delete');
$response = $client->head('http://httpbin.org/get');
$response = $client->options('http://httpbin.org/get');
$response = $client->patch('http://httpbin.org/patch');
$response = $client->post('http://httpbin.org/post');
$response = $client->put('http://httpbin.org/put');
创建一个请求:
use GuzzleHttp\Psr7\Request;
$request = new Request('PUT', 'http://httpbin.org/put');
$response = $client->send($request, ['timeout' => 2]);
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://api.github.com/repos/guzzle/guzzle');
echo $response->getStatusCode(); // 200
echo $response->getReasonPhrase(); // OK
print_r($response->getHeader('content-type')); // Array( [0] => application/json; charset=utf-8 )
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"id": 1420053, "name": "guzzle", ...}'
异步请求
$promise = $client->getAsync('http://httpbin.org/get');
$promise = $client->deleteAsync('http://httpbin.org/delete');
$promise = $client->headAsync('http://httpbin.org/get');
$promise = $client->optionsAsync('http://httpbin.org/get');
$promise = $client->patchAsync('http://httpbin.org/patch');
$promise = $client->postAsync('http://httpbin.org/post');
$promise = $client->putAsync('http://httpbin.org/put');
创建一个请求:
// Send an asynchronous request.
$request = new \GuzzleHttp\Psr7\Request('GET', 'http://httpbin.org');
$promise = $client->sendAsync($request)->then(function ($response) {
echo 'I completed! ' . $response->getBody();
});
$promise->wait();
$headers = ['X-Foo' => 'Bar'];
$body = 'Hello!';
$request = new Request('HEAD', 'http://httpbin.org/head', $headers, $body);
$promise = $client->sendAsync($request);
// Or, if you don't need to pass in a request instance:
$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
$promise = $client->requestAsync('GET', 'http://httpbin.org/get');
$promise->then(
function (ResponseInterface $res) {
echo $res->getStatusCode() . "\n";
},
function (RequestException $e) {
echo $e->getMessage() . "\n";
echo $e->getRequest()->getMethod();
}
);
并发请求
使用 Promise 和异步请求同时发送多个请求:
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
$client = new Client(['base_uri' => 'http://httpbin.org/']);
// Initiate each request but do not block
$promises = [
'image' => $client->getAsync('/image'),
'png' => $client->getAsync('/image/png'),
'jpeg' => $client->getAsync('/image/jpeg'),
'webp' => $client->getAsync('/image/webp')
];
// Wait for the requests to complete; throws a ConnectException
// if any of the requests fail
$responses = Promise\Utils::unwrap($promises);
// You can access each response using the key of the promise
echo $responses['image']->getHeader('Content-Length')[0];
echo $responses['png']->getHeader('Content-Length')[0];
// Wait for the requests to complete, even if some of them fail
$responses = Promise\Utils::settle($promises)->wait();
// Values returned above are wrapped in an array with 2 keys: "state" (either fulfilled or rejected) and "value" (contains the response)
echo $responses['image']['state']; // returns "fulfilled"
echo $responses['image']['value']->getHeader('Content-Length')[0];
echo $responses['png']['value']->getHeader('Content-Length')[0];
发送的请求数量不确定时,您可以使用 GuzzleHttp\Pool
对象:
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
$client = new Client();
$requests = function ($total) {
$uri = 'http://127.0.0.1:8126/guzzle-server/perf';
for ($i = 0; $i < $total; $i++) {
yield new Request('GET', $uri);
}
};
$pool = new Pool($client, $requests(100), [
'concurrency' => 5,
'fulfilled' => function (Response $response, $index) {
// this is delivered each successful response
},
'rejected' => function (RequestException $reason, $index) {
// this is delivered each failed request
},
]);
// Initiate the transfers and create a promise
$promise = $pool->promise();
// Force the pool of requests to complete.
$promise->wait();
或者使用闭包:
$client = new Client();
$requests = function ($total) use ($client) {
$uri = 'http://127.0.0.1:8126/guzzle-server/perf';
for ($i = 0; $i < $total; $i++) {
yield function() use ($client, $uri) {
return $client->getAsync($uri);
};
}
};
$pool = new Pool($client, $requests(100));
使用响应
code = $response->getStatusCode(); // 200
$reason = $response->getReasonPhrase(); // OK
// Check if a header exists.
if ($response->hasHeader('Content-Length')) {
echo "It exists";
}
// Get a header from the response.
echo $response->getHeader('Content-Length')[0];
// Get all of the response headers.
foreach ($response->getHeaders() as $name => $values) {
echo $name . ': ' . implode(', ', $values) . "\r\n";
}
$body = $response->getBody();
// Implicitly cast the body to a string and echo it
echo $body;
// Explicitly cast the body to a string
$stringBody = (string) $body;
// Read 10 bytes from the body
$tenBytes = $body->read(10);
// Read the remaining contents of the body as a string
$remainingBytes = $body->getContents();
httpbin
httpbin 是一个简单的 HTTP 请求和响应服务。
网址:http://httpbin.org
提供了各种服务请求地址。
参考资料
guzzle/guzzle https://github.com/guzzle/guzzle
guzzlehttp/guzzle https://packagist.org/packages/guzzlehttp/guzzle
Guzzle Documentation https://docs.guzzlephp.org/en/stable/
PSR-7 HTTP 消息接口规范 https://learnku.com/docs/psr/psr-7-http-message/1616
httpbin http://www.httpbin.org/