Skip to content

Commit 465c35c

Browse files
dbuddeboer
authored andcommitted
Upgrade php-http integration
convert to options array
1 parent cb31f52 commit 465c35c

20 files changed

+524
-536
lines changed

composer.json

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,20 @@
2020
"homepage": "https://github.com/friendsofsymfony/FOSHttpCache/contributors"
2121
}
2222
],
23+
"minimum-stability": "dev",
2324
"require": {
2425
"php": ">=5.4.8",
25-
"symfony/event-dispatcher": "^2.3||^3.0",
26-
"symfony/options-resolver": "^2.3||^3.0",
27-
"psr/http-message-implementation": "~1.0",
28-
"php-http/adapter-implementation": "^0.1.0",
29-
"php-http/discovery": "^0.1.1",
30-
"php-http/message-decorator": "^0.1.0"
26+
"symfony/event-dispatcher": "~2.3",
27+
"symfony/options-resolver": "~2.3",
28+
"php-http/client-implementation": "^1.0.0",
29+
"php-http/discovery": "^0.3.0"
3130
},
3231
"require-dev": {
3332
"mockery/mockery": "~0.9.1",
3433
"monolog/monolog": "~1.0",
35-
"php-http/guzzle6-adapter": "^0.1.0",
36-
"guzzlehttp/psr7": "^1.0",
37-
"symfony/process": "^2.3||^3.0",
38-
"symfony/http-kernel": "^2.3||^3.0"
34+
"php-http/guzzle6-adapter": "^0.2.0",
35+
"symfony/process": "~2.3",
36+
"symfony/http-kernel": "~2.3"
3937
},
4038
"suggest": {
4139
"monolog/monolog": "For logging issues while invalidating"

doc/proxy-clients.rst

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ which caching solution you use.
1212
Setup
1313
-----
1414

15-
HTTP Adapter Installation
16-
~~~~~~~~~~~~~~~~~~~~~~~~~
15+
HTTP Client Installation
16+
~~~~~~~~~~~~~~~~~~~~~~~~
1717

18-
Because the clients send invalidation requests over HTTP, an `HTTP adapter`_
19-
must be installed. Which one you need depends on the HTTP client library that
20-
you use in your project. For instance, if you use Guzzle 6 in your project,
21-
install the appropriate adapter:
18+
Because the clients send invalidation requests over HTTP, an `HTTP client`_
19+
must be installed. You can choose a client that fits for your project or
20+
an adapter to a client you already use. For instance, if you use Guzzle 6 in
21+
your project, install the appropriate adapter:
2222

2323
.. code-block:: bash
2424
@@ -28,6 +28,8 @@ You also need a `PSR-7 message implementation`_. If you use Guzzle 6, Guzzle’s
2828
implementation is already included. If you use another client, install one of
2929
the implementations. Recommended:
3030

31+
TODO: i think we need the matching adapter for the factory, if guzzle6-adapter is not installed
32+
3133
.. code-block:: bash
3234
3335
$ composer require guzzlehttp/psr7
@@ -40,13 +42,13 @@ Alternatively:
4042
4143
.. _HTTP adapter configuration:
4244

43-
HTTP Adapter Configuration
44-
~~~~~~~~~~~~~~~~~~~~~~~~~~
45+
HTTP Client Configuration
46+
~~~~~~~~~~~~~~~~~~~~~~~~~
4547

46-
By default, the proxy client will find the adapter that you have installed
47-
through Composer. But you can also pass the adapter explicitly. This is most
48-
useful when you have created a HTTP client with custom options or middleware
49-
(such as logging)::
48+
By default, the proxy client will automatically locate an HTTP client that you
49+
have installed through Composer. But you can also pass the adapter explicitly.
50+
This is most useful when you have created a HTTP client with custom options or
51+
middleware (such as logging)::
5052

5153
use GuzzleHttp\Client;
5254

@@ -66,6 +68,13 @@ Then pass that adapter to the caching proxy client::
6668
$proxyClient = new Varnish($servers, '/baseUrl', $adapter);
6769
// Varnish as example, but also possible for NGINX and Symfony
6870

71+
HTTP Message Factory Configuration
72+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73+
74+
Similar to the HTTP client, the HTTP message factory is automatically located
75+
by default. You can pass an explicit instance of the message factory if you
76+
need to.
77+
6978
.. _varnish client:
7079

7180
Varnish Client
@@ -276,6 +285,5 @@ Varnish client::
276285
Make sure to add any headers that you want to ban on to your
277286
:doc:`proxy configuration <proxy-configuration>`.
278287

279-
.. _header: http://php.net/header
280-
.. _HTTP Adapter: http://php-http.readthedocs.org/en/latest/
288+
.. _HTTP client: http://httplug.io/
281289
.. _PSR-7 message implementation: https://packagist.org/providers/psr/http-message-implementation

src/Exception/ProxyUnreachableException.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace FOS\HttpCache\Exception;
1313

14-
use Http\Adapter\Exception\HttpAdapterException;
14+
use Http\Client\Exception\RequestException;
1515

1616
/**
1717
* Thrown when a request to the reverse caching proxy fails to establish a
@@ -20,18 +20,18 @@
2020
class ProxyUnreachableException extends \RuntimeException implements HttpCacheExceptionInterface
2121
{
2222
/**
23-
* @param HttpAdapterException $adapterException
23+
* @param RequestException $adapterException
2424
*
2525
* @return ProxyUnreachableException
2626
*/
27-
public static function proxyUnreachable(HttpAdapterException $adapterException)
27+
public static function proxyUnreachable(RequestException $adapterException)
2828
{
2929
$message = sprintf(
3030
'Request to caching proxy at %s failed with message "%s"',
3131
$adapterException->getRequest()->getHeaderLine('Host'),
3232
$adapterException->getMessage()
3333
);
34-
34+
3535
return new ProxyUnreachableException(
3636
$message,
3737
0,

src/ProxyClient/AbstractProxyClient.php

Lines changed: 56 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -11,144 +11,105 @@
1111

1212
namespace FOS\HttpCache\ProxyClient;
1313

14-
use FOS\HttpCache\Exception\ExceptionCollection;
15-
use FOS\HttpCache\Exception\ProxyResponseException;
16-
use FOS\HttpCache\Exception\ProxyUnreachableException;
17-
use FOS\HttpCache\ProxyClient\Request\InvalidationRequest;
18-
use FOS\HttpCache\ProxyClient\Request\RequestQueue;
19-
use Http\Adapter\Exception\MultiHttpAdapterException;
20-
use Http\Adapter\HttpAdapter;
21-
use Http\Discovery\HttpAdapterDiscovery;
22-
use Psr\Http\Message\ResponseInterface;
14+
use FOS\HttpCache\ProxyClient\Http\HttpAdapter;
15+
use Http\Client\HttpAsyncClient;
16+
use Http\Discovery\HttpAsyncClientDiscovery;
17+
use Http\Discovery\MessageFactoryDiscovery;
18+
use Http\Message\MessageFactory;
19+
use Psr\Http\Message\UriInterface;
20+
use Symfony\Component\OptionsResolver\OptionsResolver;
2321

2422
/**
25-
* Abstract caching proxy client
23+
* Abstract HTTP based caching proxy client.
2624
*
2725
* @author David de Boer <[email protected]>
2826
*/
2927
abstract class AbstractProxyClient implements ProxyClientInterface
3028
{
3129
/**
32-
* HTTP client
30+
* HTTP client adapter.
3331
*
3432
* @var HttpAdapter
3533
*/
36-
private $httpAdapter;
34+
protected $httpAdapter;
3735

3836
/**
39-
* Request queue
37+
* @var MessageFactory
38+
*/
39+
protected $messageFactory;
40+
41+
/**
42+
* The options configured in the constructor argument or default values.
4043
*
41-
* @var RequestQueue
44+
* @var array The resolved options.
4245
*/
43-
protected $queue;
46+
protected $options;
4447

4548
/**
4649
* Constructor
4750
*
48-
* @param array $servers Caching proxy server hostnames or IP
49-
* addresses, including port if not port 80.
50-
* E.g. ['127.0.0.1:6081']
51-
* @param string $baseUri Default application hostname, optionally
52-
* including base URL, for purge and refresh
53-
* requests (optional). This is required if
54-
* you purge and refresh paths instead of
55-
* absolute URLs.
56-
* @param HttpAdapter $httpAdapter If no HTTP adapter is supplied, a default
57-
* one will be created.
51+
* Supported options:
52+
*
53+
* - base_uri Default application hostname, optionally including base URL,
54+
* for purge and refresh requests (optional). This is required if you
55+
* purge and refresh paths instead of absolute URLs.
56+
*
57+
* @param array $servers Caching proxy server hostnames or IP
58+
* addresses, including port if not port 80.
59+
* E.g. ['127.0.0.1:6081']
60+
* @param array $options List of options for the client.
61+
* @param HttpAsyncClient|null $httpClient Client capable of sending HTTP requests. If no
62+
* client is supplied, a default one is created.
63+
* @param MessageFactory|null $messageFactory Factory for PSR-7 messages. If none supplied,
64+
* a default one is created.
5865
*/
5966
public function __construct(
6067
array $servers,
61-
$baseUri = null,
62-
HttpAdapter $httpAdapter = null
68+
array $options = [],
69+
HttpAsyncClient $httpClient = null,
70+
MessageFactory $messageFactory = null
6371
) {
64-
$this->httpAdapter = $httpAdapter ?: HttpAdapterDiscovery::find();
65-
$this->initQueue($servers, $baseUri);
72+
if (!$httpClient) {
73+
$httpClient = HttpAsyncClientDiscovery::find();
74+
}
75+
$this->options = $this->getDefaultOptions()->resolve($options);
76+
$this->httpAdapter = new HttpAdapter($servers, $this->options['base_uri'], $httpClient);
77+
$this->messageFactory = $messageFactory ?: MessageFactoryDiscovery::find();
6678
}
6779

6880
/**
6981
* {@inheritdoc}
7082
*/
7183
public function flush()
7284
{
73-
if (0 === $this->queue->count()) {
74-
return 0;
75-
}
76-
77-
$queue = clone $this->queue;
78-
$this->queue->clear();
79-
80-
try {
81-
$responses = $this->httpAdapter->sendRequests($queue->all());
82-
} catch (MultiHttpAdapterException $e) {
83-
// Handle all networking errors: php-http only throws an exception
84-
// if no response is available.
85-
$collection = new ExceptionCollection();
86-
foreach ($e->getExceptions() as $exception) {
87-
// php-http only throws an exception if no response is available
88-
if (!$exception->getResponse()) {
89-
// Assume networking error if no response was returned.
90-
$collection->add(
91-
ProxyUnreachableException::proxyUnreachable($exception)
92-
);
93-
}
94-
}
95-
96-
foreach ($this->handleErrorResponses($e->getResponses()) as $exception) {
97-
$collection->add($exception);
98-
}
99-
100-
throw $collection;
101-
}
102-
103-
$exceptions = $this->handleErrorResponses($responses);
104-
if (count($exceptions) > 0) {
105-
throw new ExceptionCollection($exceptions);
106-
}
107-
108-
return count($queue);
85+
return $this->httpAdapter->flush();
10986
}
11087

11188
/**
112-
* Add invalidation reqest to the queue
89+
* Get options resolver with default settings.
11390
*
114-
* @param string $method HTTP method
115-
* @param string $url HTTP URL
116-
* @param array $headers HTTP headers
91+
* @return OptionsResolver
11792
*/
118-
protected function queueRequest($method, $url, array $headers = [])
93+
protected function getDefaultOptions()
11994
{
120-
$this->queue->add(new InvalidationRequest($method, $url, $headers));
121-
}
95+
$resolver = new OptionsResolver();
96+
$resolver->setDefault('base_uri', null);
12297

123-
/**
124-
* Initialize the request queue
125-
*
126-
* @param array $servers
127-
* @param string $baseUri
128-
*/
129-
protected function initQueue(array $servers, $baseUri)
130-
{
131-
$this->queue = new RequestQueue($servers, $baseUri);
98+
return $resolver;
13299
}
133100

134101
/**
135-
* @param ResponseInterface[] $responses
102+
* Create a request and queue it with the HttpAdapter.
136103
*
137-
* @return ProxyResponseException[]
104+
* @param string $method
105+
* @param string|UriInterface $url
106+
* @param array $headers
138107
*/
139-
private function handleErrorResponses(array $responses)
108+
protected function queueRequest($method, $url, array $headers)
140109
{
141-
$exceptions = [];
142-
143-
foreach ($responses as $response) {
144-
if ($response->getStatusCode() >= 400
145-
&& $response->getStatusCode() < 600
146-
) {
147-
$exceptions[] = ProxyResponseException::proxyResponse($response);
148-
}
149-
}
150-
151-
return $exceptions;
110+
$this->httpAdapter->invalidate(
111+
$this->messageFactory->createRequest($method, $url, $headers)
112+
);
152113
}
153114

154115
/**

0 commit comments

Comments
 (0)