What is the difference between
guzzle/guzzle
and
guzzlehttp/guzzle?
FOSHttpCache needs to send HTTP requests to varnish for cache invalidation
=> Márk Sági-Kazár
=> Matthew Weier O'Phinney
How to create an object without knowing the class? PSR-17
interface RequestFactoryInterface
{
function createRequest(string $method, $uri)
: RequestInterface;
}
=> Woody Gilk
How to send that request? PSR-18
interface ClientInterface
{
function sendRequest(RequestInterface $request)
: ResponseInterface;
}
private RequestFactoryInterface $reqFactory;
private ClientInterface $httpClient;
public function getProduct(string $id): Product
{
$url = '/api/product/'.$id;
$req = $reqFactory->createRequest('GET', $url);
$response = $this->client->sendRequest($req);
if (200 !== $response->getStatusCode()) {
// error handling ...
}
// deserialize body into model...
=> Tobias Nyholm
sendRequest(RequestInterface $request, $config)
public function __construct(
ClientInterface $publicHttpClient,
ClientInterface $apiHttpClient
) {
...
API client with host and base path configured, authentication already set up
"require": {
"psr/http-client-implementation": "^1.0"
},
"require-dev": {
"guzzlehttp/guzzle": "^7.4"
}
What about the cute elephant?
public function handleRequest(
RequestInterface $request,
callable $next,
callable $first
): Promise;
CachePlugin::clientCache - max-age, no-cache
CachePlugin::serverCache - additionally: private
/**
* @param RequestInterface[] The requests to send
*
* @throws BatchException If any request threw
*/
public function sendRequests(
array $requests
): BatchResult
public function get($uri, array $headers = []):
public function post($uri, array $headers = [],
public function put($uri, array $headers = [],
public function send(string $method, $uri, arr
composer require php-http/discovery
public function __construct(
?ClientInterface $httpClient = null,
?RequestFactoryInterface $requestF = null
) {
$this->httpClient = $httpClient ?:
Psr18ClientDiscovery::find();
$this->requestF = $requestF ?:
Psr17FactoryDiscovery::findRequestFactory();
...
Still allow user to provide client instance!
httplug:
clients:
app:
http_methods_client: true
plugins:
- header_set:
headers:
"User-Agent": "demo-app"
private HttpMethodsClient $httpClient;
public function status(): Response {
try {
$r = $this->httpClient->get('http://php.net/');
} catch (Exception $e) {
return new Response('Failed', 502);
}
return new Response(200 === $r->getStatusCode()
? 'Success'
: 'Error');
sendAsync(RequestInterface $request): Promise; Promise::wait(): ResponseInterface;
PHP 8.1 introduces the Fibers concept
interface Promise
{
public const PENDING = 'pending';
public const FULFILLED = 'fulfilled';
public const REJECTED = 'rejected';
public function then(?callable $onFulfilled,
public function getState();
public function wait($unwrap = true);
}
try {
$promises = [];
foreach ($uris as $u) {
$promises[$u] = $httpClient->sendAsyncRequest(
$requestFactory->createRequest('GET', $u)
);
}
} catch (\Exception $e) {
return new Response('Configuration error', 500);
}
foreach ($promises as $uri => $promise) {
$s .= $uri.':';
try {
$r = $promise->wait();
if (200 === $r->getStatusCode()) {
$s .= 'Up and running';
} else {
$s .= 'Error: '.$r->getStatusCode();
}
} catch (\Exception $e) {
$s .= 'Network Error: '.$e->getMessage();
}
}
$results = [];
$promises = [];
foreach ($uris as $u) {
$promise = $httpClient->sendAsyncRequest(
$requestFactory->createRequest('GET', $u));
$onFulfilled = function (ResponseInterface $r)
use ($u, $results) {
if (200 === $r->getStatusCode()) {
$results[$u] = 'Up and running';
} else {
$results[$u] = 'Error: '.$r->getStatusCode();
}
};
}
...
$onRejected = function (Exception $r)
use ($u, $results) {
$results[$u] = 'Error: '.$e->getMessage();
};
$promise->then($onFulfilled, $onRejected);
$promises[] = $promise;
}
} catch (Exception $e) {
return new Response('Configuration error', 500);
}
foreach ($promises as $promise) {
$promise->wait(false);
}
foreach ($results as $u => $text) {
$s .= $uri.':'.text;
}