12
12
namespace FOS \HttpCache \ProxyClient ;
13
13
14
14
use FOS \HttpCache \Exception \ExceptionCollection ;
15
- use FOS \HttpCache \Exception \InvalidUrlException ;
16
- use FOS \HttpCache \Exception \ProxyResponseException ;
17
15
use FOS \HttpCache \Exception \ProxyUnreachableException ;
18
- use Guzzle \Http \Client ;
19
- use Guzzle \Http \ClientInterface ;
20
- use Guzzle \Http \Exception \CurlException ;
21
- use Guzzle \Common \Exception \ExceptionCollection as GuzzleExceptionCollection ;
22
- use Guzzle \Http \Exception \RequestException ;
23
- use Guzzle \Http \Message \RequestInterface ;
16
+ use FOS \HttpCache \ProxyClient \Request \InvalidationRequest ;
17
+ use FOS \HttpCache \ProxyClient \Request \RequestQueue ;
18
+ use Ivory \HttpAdapter \HttpAdapterFactory ;
19
+ use Ivory \HttpAdapter \HttpAdapterInterface ;
20
+ use Ivory \HttpAdapter \MultiHttpAdapterException ;
24
21
25
22
/**
26
- * Guzzle-based abstract caching proxy client
23
+ * Abstract caching proxy client
27
24
*
28
25
* @author David de Boer <[email protected] >
29
26
*/
30
27
abstract class AbstractProxyClient implements ProxyClientInterface
31
28
{
32
- /**
33
- * IP addresses/hostnames of all caching proxy servers
34
- *
35
- * @var array
36
- */
37
- private $ servers ;
38
-
39
29
/**
40
30
* HTTP client
41
31
*
42
- * @var ClientInterface
32
+ * @var HttpAdapterInterface
43
33
*/
44
- private $ client ;
34
+ private $ httpAdapter ;
45
35
46
36
/**
47
37
* Request queue
48
38
*
49
- * @var array|RequestInterface[]
39
+ * @var RequestQueue
50
40
*/
51
- private $ queue ;
41
+ protected $ queue ;
52
42
53
43
/**
54
44
* Constructor
@@ -61,238 +51,59 @@ abstract class AbstractProxyClient implements ProxyClientInterface
61
51
* requests (optional). This is required if
62
52
* you purge and refresh paths instead of
63
53
* absolute URLs.
64
- * @param ClientInterface $client HTTP client (optional). If no HTTP client
65
- * is supplied, a default one will be
66
- * created.
54
+ * @param HttpAdapterInterface $httpAdapter If no HTTP client is supplied, a
55
+ * default one will be created.
67
56
*/
68
- public function __construct (array $ servers , $ baseUrl = null , ClientInterface $ client = null )
69
- {
70
- $ this ->client = $ client ?: new Client ();
71
- $ this ->setServers ($ servers );
72
- $ this ->setBaseUrl ($ baseUrl );
73
- }
74
-
75
- /**
76
- * Set caching proxy servers
77
- *
78
- * @param array $servers Caching proxy proxy server hostnames or IP
79
- * addresses, including port if not port 80.
80
- * E.g. array('127.0.0.1:6081')
81
- *
82
- * @throws InvalidUrlException If server is invalid or contains URL
83
- * parts other than scheme, host, port
84
- */
85
- public function setServers (array $ servers )
86
- {
87
- $ this ->servers = array ();
88
- foreach ($ servers as $ server ) {
89
- $ this ->servers [] = $ this ->filterUrl ($ server , array ('scheme ' , 'host ' , 'port ' ));
90
- }
91
- }
92
-
93
- /**
94
- * Set application hostname, optionally including a base URL, for purge and
95
- * refresh requests
96
- *
97
- * @param string $url Your application’s base URL or hostname
98
- */
99
- public function setBaseUrl ($ url )
100
- {
101
- if ($ url ) {
102
- $ url = $ this ->filterUrl ($ url );
103
- }
104
-
105
- $ this ->client ->setBaseUrl ($ url );
57
+ public function __construct (
58
+ array $ servers ,
59
+ $ baseUrl = null ,
60
+ HttpAdapterInterface $ httpAdapter = null
61
+ ) {
62
+ $ this ->httpAdapter = $ httpAdapter ?: HttpAdapterFactory::guess ();
63
+ $ this ->initQueue ($ servers , $ baseUrl );
106
64
}
107
65
108
66
/**
109
67
* {@inheritdoc}
110
68
*/
111
69
public function flush ()
112
70
{
113
- $ queue = $ this ->queue ;
114
- if (0 === count ($ queue )) {
71
+ if (0 === $ this ->queue ->count ()) {
115
72
return 0 ;
116
73
}
117
-
118
- $ this ->queue = array ();
119
- $ this ->sendRequests ($ queue );
120
-
121
- return count ($ queue );
122
- }
123
-
124
- /**
125
- * Add a request to the queue
126
- *
127
- * @param string $method HTTP method
128
- * @param string $url URL
129
- * @param array $headers HTTP headers
130
- */
131
- protected function queueRequest ($ method , $ url , array $ headers = array ())
132
- {
133
- $ signature = $ this ->getSignature ($ method , $ url , $ headers );
134
- if (!isset ($ this ->queue [$ signature ])) {
135
- $ this ->queue [$ signature ] = $ this ->createRequest ($ method , $ url , $ headers );
136
- }
137
- }
138
-
139
- /**
140
- * Calculate a unique hash for the request, based on all significant information.
141
- *
142
- * @param string $method HTTP method
143
- * @param string $url URL
144
- * @param array $headers HTTP headers
145
- *
146
- * @return string A hash value for this request.
147
- */
148
- private function getSignature ($ method , $ url , array $ headers )
149
- {
150
- ksort ($ headers );
151
-
152
- return md5 ($ method . "\n" . $ url . "\n" . var_export ($ headers , true ));
153
- }
154
-
155
- /**
156
- * Create request
157
- *
158
- * @param string $method HTTP method
159
- * @param string $url URL
160
- * @param array $headers HTTP headers
161
- *
162
- * @return RequestInterface
163
- */
164
- protected function createRequest ($ method , $ url , array $ headers = array ())
165
- {
166
- return $ this ->client ->createRequest ($ method , $ url , $ headers );
167
- }
168
-
169
- /**
170
- * Sends all requests to each caching proxy server
171
- *
172
- * Requests are sent in parallel to minimise impact on performance.
173
- *
174
- * @param RequestInterface[] $requests Requests
175
- *
176
- * @throws ExceptionCollection
177
- */
178
- private function sendRequests (array $ requests )
179
- {
180
- $ allRequests = array ();
181
-
182
- foreach ($ requests as $ request ) {
183
- $ headers = $ request ->getHeaders ()->toArray ();
184
- // Force to re-create Host header if empty, as Apache chokes on this. See #128 for discussion.
185
- if (empty ($ headers ['Host ' ])) {
186
- unset( $ headers ['Host ' ] );
187
- }
188
- foreach ($ this ->servers as $ server ) {
189
- $ proxyRequest = $ this ->client ->createRequest (
190
- $ request ->getMethod (),
191
- $ server . $ request ->getResource (),
192
- $ headers
193
- );
194
- $ allRequests [] = $ proxyRequest ;
195
- }
196
- }
74
+
75
+ $ queue = clone $ this ->queue ;
76
+ $ this ->queue ->clear ();
197
77
198
78
try {
199
- $ this ->client ->send ($ allRequests );
200
- } catch (GuzzleExceptionCollection $ e ) {
201
- $ this ->handleException ($ e );
202
- }
203
- }
204
-
205
- /**
206
- * Handle request exception
207
- *
208
- * @param GuzzleExceptionCollection $exceptions
209
- *
210
- * @throws ExceptionCollection
211
- */
212
- protected function handleException (GuzzleExceptionCollection $ exceptions )
213
- {
214
- $ collection = new ExceptionCollection ();
215
-
216
- foreach ($ exceptions as $ exception ) {
217
- if ($ exception instanceof CurlException) {
218
- // Caching proxy unreachable
219
- $ e = ProxyUnreachableException::proxyUnreachable (
220
- $ exception ->getRequest ()->getHost (),
221
- $ exception ->getMessage (),
222
- $ exception ->getRequest ()->getRawHeaders (),
223
- $ exception
224
- );
225
- } elseif ($ exception instanceof RequestException) {
226
- // Other error
227
- $ e = ProxyResponseException::proxyResponse (
228
- $ exception ->getRequest ()->getHost (),
229
- $ exception ->getCode (),
230
- $ exception ->getMessage (),
231
- $ exception ->getRequest ()->getRawHeaders (),
232
- $ exception
79
+ $ responses = $ this ->httpAdapter ->sendRequests ($ queue ->all ());
80
+ } catch (MultiHttpAdapterException $ e ) {
81
+ $ collection = new ExceptionCollection ();
82
+ foreach ($ e ->getExceptions () as $ exception ) {
83
+ $ collection ->add (
84
+ ProxyUnreachableException::proxyUnreachable (
85
+ $ exception ->getRequest ()->getHeader ('Host ' ),
86
+ $ exception ->getMessage (),
87
+ null ,
88
+ $ exception
89
+ )
233
90
);
234
- } else {
235
- // Unexpected exception type
236
- $ e = $ exception ;
237
91
}
238
92
239
- $ collection-> add ( $ e ) ;
93
+ throw $ collection ;
240
94
}
241
-
242
- throw $ collection ;
95
+
96
+ return count ( $ responses ) ;
243
97
}
244
-
245
- /**
246
- * Filter a URL
247
- *
248
- * Prefix the URL with "http://" if it has no scheme, then check the URL
249
- * for validity. You can specify what parts of the URL are allowed.
250
- *
251
- * @param string $url
252
- * @param string[] $allowedParts Array of allowed URL parts (optional)
253
- *
254
- * @throws InvalidUrlException If URL is invalid, the scheme is not http or
255
- * contains parts that are not expected.
256
- *
257
- * @return string The URL (with default scheme if there was no scheme)
258
- */
259
- protected function filterUrl ($ url , array $ allowedParts = array ())
98
+
99
+ protected function queueRequest ($ method , $ url , array $ headers = array ())
260
100
{
261
- // parse_url doesn’t work properly when no scheme is supplied, so
262
- // prefix URL with HTTP scheme if necessary.
263
- if (false === strpos ($ url , ':// ' )) {
264
- $ url = sprintf ('%s://%s ' , $ this ->getDefaultScheme (), $ url );
265
- }
266
-
267
- if (!$ parts = parse_url ($ url )) {
268
- throw InvalidUrlException::invalidUrl ($ url );
269
- }
270
- if (empty ($ parts ['scheme ' ])) {
271
- throw InvalidUrlException::invalidUrl ($ url , 'empty scheme ' );
272
- }
273
-
274
- if (!in_array (strtolower ($ parts ['scheme ' ]), $ this ->getAllowedSchemes ())) {
275
- throw InvalidUrlException::invalidUrlScheme ($ url , $ parts ['scheme ' ], $ this ->getAllowedSchemes ());
276
- }
277
-
278
- if (count ($ allowedParts ) > 0 ) {
279
- $ diff = array_diff (array_keys ($ parts ), $ allowedParts );
280
- if (count ($ diff ) > 0 ) {
281
- throw InvalidUrlException::invalidUrlParts ($ url , $ allowedParts );
282
- }
283
- }
284
-
285
- return $ url ;
101
+ $ this ->queue ->add (new InvalidationRequest ($ method , $ url , $ headers ));
286
102
}
287
-
288
- /**
289
- * Get default scheme
290
- *
291
- * @return string
292
- */
293
- protected function getDefaultScheme ()
103
+
104
+ protected function initQueue (array $ servers , $ baseUrl )
294
105
{
295
- return ' http ' ;
106
+ $ this -> queue = new RequestQueue ( $ servers , $ baseUrl ) ;
296
107
}
297
108
298
109
/**
0 commit comments