commit | author | age
|
2207d6
|
1 |
Guzzle Upgrade Guide |
W |
2 |
==================== |
|
3 |
|
|
4 |
5.0 to 6.0 |
|
5 |
---------- |
|
6 |
|
|
7 |
Guzzle now uses [PSR-7](http://www.php-fig.org/psr/psr-7/) for HTTP messages. |
|
8 |
Due to the fact that these messages are immutable, this prompted a refactoring |
|
9 |
of Guzzle to use a middleware based system rather than an event system. Any |
|
10 |
HTTP message interaction (e.g., `GuzzleHttp\Message\Request`) need to be |
|
11 |
updated to work with the new immutable PSR-7 request and response objects. Any |
|
12 |
event listeners or subscribers need to be updated to become middleware |
|
13 |
functions that wrap handlers (or are injected into a |
|
14 |
`GuzzleHttp\HandlerStack`). |
|
15 |
|
|
16 |
- Removed `GuzzleHttp\BatchResults` |
|
17 |
- Removed `GuzzleHttp\Collection` |
|
18 |
- Removed `GuzzleHttp\HasDataTrait` |
|
19 |
- Removed `GuzzleHttp\ToArrayInterface` |
|
20 |
- The `guzzlehttp/streams` dependency has been removed. Stream functionality |
|
21 |
is now present in the `GuzzleHttp\Psr7` namespace provided by the |
|
22 |
`guzzlehttp/psr7` package. |
|
23 |
- Guzzle no longer uses ReactPHP promises and now uses the |
|
24 |
`guzzlehttp/promises` library. We use a custom promise library for three |
|
25 |
significant reasons: |
|
26 |
1. React promises (at the time of writing this) are recursive. Promise |
|
27 |
chaining and promise resolution will eventually blow the stack. Guzzle |
|
28 |
promises are not recursive as they use a sort of trampolining technique. |
|
29 |
Note: there has been movement in the React project to modify promises to |
|
30 |
no longer utilize recursion. |
|
31 |
2. Guzzle needs to have the ability to synchronously block on a promise to |
|
32 |
wait for a result. Guzzle promises allows this functionality (and does |
|
33 |
not require the use of recursion). |
|
34 |
3. Because we need to be able to wait on a result, doing so using React |
|
35 |
promises requires wrapping react promises with RingPHP futures. This |
|
36 |
overhead is no longer needed, reducing stack sizes, reducing complexity, |
|
37 |
and improving performance. |
|
38 |
- `GuzzleHttp\Mimetypes` has been moved to a function in |
|
39 |
`GuzzleHttp\Psr7\mimetype_from_extension` and |
|
40 |
`GuzzleHttp\Psr7\mimetype_from_filename`. |
|
41 |
- `GuzzleHttp\Query` and `GuzzleHttp\QueryParser` have been removed. Query |
|
42 |
strings must now be passed into request objects as strings, or provided to |
|
43 |
the `query` request option when creating requests with clients. The `query` |
|
44 |
option uses PHP's `http_build_query` to convert an array to a string. If you |
|
45 |
need a different serialization technique, you will need to pass the query |
|
46 |
string in as a string. There are a couple helper functions that will make |
|
47 |
working with query strings easier: `GuzzleHttp\Psr7\parse_query` and |
|
48 |
`GuzzleHttp\Psr7\build_query`. |
|
49 |
- Guzzle no longer has a dependency on RingPHP. Due to the use of a middleware |
|
50 |
system based on PSR-7, using RingPHP and it's middleware system as well adds |
|
51 |
more complexity than the benefits it provides. All HTTP handlers that were |
|
52 |
present in RingPHP have been modified to work directly with PSR-7 messages |
|
53 |
and placed in the `GuzzleHttp\Handler` namespace. This significantly reduces |
|
54 |
complexity in Guzzle, removes a dependency, and improves performance. RingPHP |
|
55 |
will be maintained for Guzzle 5 support, but will no longer be a part of |
|
56 |
Guzzle 6. |
|
57 |
- As Guzzle now uses a middleware based systems the event system and RingPHP |
|
58 |
integration has been removed. Note: while the event system has been removed, |
|
59 |
it is possible to add your own type of event system that is powered by the |
|
60 |
middleware system. |
|
61 |
- Removed the `Event` namespace. |
|
62 |
- Removed the `Subscriber` namespace. |
|
63 |
- Removed `Transaction` class |
|
64 |
- Removed `RequestFsm` |
|
65 |
- Removed `RingBridge` |
|
66 |
- `GuzzleHttp\Subscriber\Cookie` is now provided by |
|
67 |
`GuzzleHttp\Middleware::cookies` |
|
68 |
- `GuzzleHttp\Subscriber\HttpError` is now provided by |
|
69 |
`GuzzleHttp\Middleware::httpError` |
|
70 |
- `GuzzleHttp\Subscriber\History` is now provided by |
|
71 |
`GuzzleHttp\Middleware::history` |
|
72 |
- `GuzzleHttp\Subscriber\Mock` is now provided by |
|
73 |
`GuzzleHttp\Handler\MockHandler` |
|
74 |
- `GuzzleHttp\Subscriber\Prepare` is now provided by |
|
75 |
`GuzzleHttp\PrepareBodyMiddleware` |
|
76 |
- `GuzzleHttp\Subscriber\Redirect` is now provided by |
|
77 |
`GuzzleHttp\RedirectMiddleware` |
|
78 |
- Guzzle now uses `Psr\Http\Message\UriInterface` (implements in |
|
79 |
`GuzzleHttp\Psr7\Uri`) for URI support. `GuzzleHttp\Url` is now gone. |
|
80 |
- Static functions in `GuzzleHttp\Utils` have been moved to namespaced |
|
81 |
functions under the `GuzzleHttp` namespace. This requires either a Composer |
|
82 |
based autoloader or you to include functions.php. |
|
83 |
- `GuzzleHttp\ClientInterface::getDefaultOption` has been renamed to |
|
84 |
`GuzzleHttp\ClientInterface::getConfig`. |
|
85 |
- `GuzzleHttp\ClientInterface::setDefaultOption` has been removed. |
|
86 |
- The `json` and `xml` methods of response objects has been removed. With the |
|
87 |
migration to strictly adhering to PSR-7 as the interface for Guzzle messages, |
|
88 |
adding methods to message interfaces would actually require Guzzle messages |
|
89 |
to extend from PSR-7 messages rather then work with them directly. |
|
90 |
|
|
91 |
## Migrating to middleware |
|
92 |
|
|
93 |
The change to PSR-7 unfortunately required significant refactoring to Guzzle |
|
94 |
due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event |
|
95 |
system from plugins. The event system relied on mutability of HTTP messages and |
|
96 |
side effects in order to work. With immutable messages, you have to change your |
|
97 |
workflow to become more about either returning a value (e.g., functional |
|
98 |
middlewares) or setting a value on an object. Guzzle v6 has chosen the |
|
99 |
functional middleware approach. |
|
100 |
|
|
101 |
Instead of using the event system to listen for things like the `before` event, |
|
102 |
you now create a stack based middleware function that intercepts a request on |
|
103 |
the way in and the promise of the response on the way out. This is a much |
|
104 |
simpler and more predictable approach than the event system and works nicely |
|
105 |
with PSR-7 middleware. Due to the use of promises, the middleware system is |
|
106 |
also asynchronous. |
|
107 |
|
|
108 |
v5: |
|
109 |
|
|
110 |
```php |
|
111 |
use GuzzleHttp\Event\BeforeEvent; |
|
112 |
$client = new GuzzleHttp\Client(); |
|
113 |
// Get the emitter and listen to the before event. |
|
114 |
$client->getEmitter()->on('before', function (BeforeEvent $e) { |
|
115 |
// Guzzle v5 events relied on mutation |
|
116 |
$e->getRequest()->setHeader('X-Foo', 'Bar'); |
|
117 |
}); |
|
118 |
``` |
|
119 |
|
|
120 |
v6: |
|
121 |
|
|
122 |
In v6, you can modify the request before it is sent using the `mapRequest` |
|
123 |
middleware. The idiomatic way in v6 to modify the request/response lifecycle is |
|
124 |
to setup a handler middleware stack up front and inject the handler into a |
|
125 |
client. |
|
126 |
|
|
127 |
```php |
|
128 |
use GuzzleHttp\Middleware; |
|
129 |
// Create a handler stack that has all of the default middlewares attached |
|
130 |
$handler = GuzzleHttp\HandlerStack::create(); |
|
131 |
// Push the handler onto the handler stack |
|
132 |
$handler->push(Middleware::mapRequest(function (RequestInterface $request) { |
|
133 |
// Notice that we have to return a request object |
|
134 |
return $request->withHeader('X-Foo', 'Bar'); |
|
135 |
})); |
|
136 |
// Inject the handler into the client |
|
137 |
$client = new GuzzleHttp\Client(['handler' => $handler]); |
|
138 |
``` |
|
139 |
|
|
140 |
## POST Requests |
|
141 |
|
|
142 |
This version added the [`form_params`](http://guzzle.readthedocs.org/en/latest/request-options.html#form_params) |
|
143 |
and `multipart` request options. `form_params` is an associative array of |
|
144 |
strings or array of strings and is used to serialize an |
|
145 |
`application/x-www-form-urlencoded` POST request. The |
|
146 |
[`multipart`](http://guzzle.readthedocs.org/en/latest/request-options.html#multipart) |
|
147 |
option is now used to send a multipart/form-data POST request. |
|
148 |
|
|
149 |
`GuzzleHttp\Post\PostFile` has been removed. Use the `multipart` option to add |
|
150 |
POST files to a multipart/form-data request. |
|
151 |
|
|
152 |
The `body` option no longer accepts an array to send POST requests. Please use |
|
153 |
`multipart` or `form_params` instead. |
|
154 |
|
|
155 |
The `base_url` option has been renamed to `base_uri`. |
|
156 |
|
|
157 |
4.x to 5.0 |
|
158 |
---------- |
|
159 |
|
|
160 |
## Rewritten Adapter Layer |
|
161 |
|
|
162 |
Guzzle now uses [RingPHP](http://ringphp.readthedocs.org/en/latest) to send |
|
163 |
HTTP requests. The `adapter` option in a `GuzzleHttp\Client` constructor |
|
164 |
is still supported, but it has now been renamed to `handler`. Instead of |
|
165 |
passing a `GuzzleHttp\Adapter\AdapterInterface`, you must now pass a PHP |
|
166 |
`callable` that follows the RingPHP specification. |
|
167 |
|
|
168 |
## Removed Fluent Interfaces |
|
169 |
|
|
170 |
[Fluent interfaces were removed](http://ocramius.github.io/blog/fluent-interfaces-are-evil) |
|
171 |
from the following classes: |
|
172 |
|
|
173 |
- `GuzzleHttp\Collection` |
|
174 |
- `GuzzleHttp\Url` |
|
175 |
- `GuzzleHttp\Query` |
|
176 |
- `GuzzleHttp\Post\PostBody` |
|
177 |
- `GuzzleHttp\Cookie\SetCookie` |
|
178 |
|
|
179 |
## Removed functions.php |
|
180 |
|
|
181 |
Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following |
|
182 |
functions can be used as replacements. |
|
183 |
|
|
184 |
- `GuzzleHttp\json_decode` -> `GuzzleHttp\Utils::jsonDecode` |
|
185 |
- `GuzzleHttp\get_path` -> `GuzzleHttp\Utils::getPath` |
|
186 |
- `GuzzleHttp\Utils::setPath` -> `GuzzleHttp\set_path` |
|
187 |
- `GuzzleHttp\Pool::batch` -> `GuzzleHttp\batch`. This function is, however, |
|
188 |
deprecated in favor of using `GuzzleHttp\Pool::batch()`. |
|
189 |
|
|
190 |
The "procedural" global client has been removed with no replacement (e.g., |
|
191 |
`GuzzleHttp\get()`, `GuzzleHttp\post()`, etc.). Use a `GuzzleHttp\Client` |
|
192 |
object as a replacement. |
|
193 |
|
|
194 |
## `throwImmediately` has been removed |
|
195 |
|
|
196 |
The concept of "throwImmediately" has been removed from exceptions and error |
|
197 |
events. This control mechanism was used to stop a transfer of concurrent |
|
198 |
requests from completing. This can now be handled by throwing the exception or |
|
199 |
by cancelling a pool of requests or each outstanding future request |
|
200 |
individually. |
|
201 |
|
|
202 |
## headers event has been removed |
|
203 |
|
|
204 |
Removed the "headers" event. This event was only useful for changing the |
|
205 |
body a response once the headers of the response were known. You can implement |
|
206 |
a similar behavior in a number of ways. One example might be to use a |
|
207 |
FnStream that has access to the transaction being sent. For example, when the |
|
208 |
first byte is written, you could check if the response headers match your |
|
209 |
expectations, and if so, change the actual stream body that is being |
|
210 |
written to. |
|
211 |
|
|
212 |
## Updates to HTTP Messages |
|
213 |
|
|
214 |
Removed the `asArray` parameter from |
|
215 |
`GuzzleHttp\Message\MessageInterface::getHeader`. If you want to get a header |
|
216 |
value as an array, then use the newly added `getHeaderAsArray()` method of |
|
217 |
`MessageInterface`. This change makes the Guzzle interfaces compatible with |
|
218 |
the PSR-7 interfaces. |
|
219 |
|
|
220 |
3.x to 4.0 |
|
221 |
---------- |
|
222 |
|
|
223 |
## Overarching changes: |
|
224 |
|
|
225 |
- Now requires PHP 5.4 or greater. |
|
226 |
- No longer requires cURL to send requests. |
|
227 |
- Guzzle no longer wraps every exception it throws. Only exceptions that are |
|
228 |
recoverable are now wrapped by Guzzle. |
|
229 |
- Various namespaces have been removed or renamed. |
|
230 |
- No longer requiring the Symfony EventDispatcher. A custom event dispatcher |
|
231 |
based on the Symfony EventDispatcher is |
|
232 |
now utilized in `GuzzleHttp\Event\EmitterInterface` (resulting in significant |
|
233 |
speed and functionality improvements). |
|
234 |
|
|
235 |
Changes per Guzzle 3.x namespace are described below. |
|
236 |
|
|
237 |
## Batch |
|
238 |
|
|
239 |
The `Guzzle\Batch` namespace has been removed. This is best left to |
|
240 |
third-parties to implement on top of Guzzle's core HTTP library. |
|
241 |
|
|
242 |
## Cache |
|
243 |
|
|
244 |
The `Guzzle\Cache` namespace has been removed. (Todo: No suitable replacement |
|
245 |
has been implemented yet, but hoping to utilize a PSR cache interface). |
|
246 |
|
|
247 |
## Common |
|
248 |
|
|
249 |
- Removed all of the wrapped exceptions. It's better to use the standard PHP |
|
250 |
library for unrecoverable exceptions. |
|
251 |
- `FromConfigInterface` has been removed. |
|
252 |
- `Guzzle\Common\Version` has been removed. The VERSION constant can be found |
|
253 |
at `GuzzleHttp\ClientInterface::VERSION`. |
|
254 |
|
|
255 |
### Collection |
|
256 |
|
|
257 |
- `getAll` has been removed. Use `toArray` to convert a collection to an array. |
|
258 |
- `inject` has been removed. |
|
259 |
- `keySearch` has been removed. |
|
260 |
- `getPath` no longer supports wildcard expressions. Use something better like |
|
261 |
JMESPath for this. |
|
262 |
- `setPath` now supports appending to an existing array via the `[]` notation. |
|
263 |
|
|
264 |
### Events |
|
265 |
|
|
266 |
Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses |
|
267 |
`GuzzleHttp\Event\Emitter`. |
|
268 |
|
|
269 |
- `Symfony\Component\EventDispatcher\EventDispatcherInterface` is replaced by |
|
270 |
`GuzzleHttp\Event\EmitterInterface`. |
|
271 |
- `Symfony\Component\EventDispatcher\EventDispatcher` is replaced by |
|
272 |
`GuzzleHttp\Event\Emitter`. |
|
273 |
- `Symfony\Component\EventDispatcher\Event` is replaced by |
|
274 |
`GuzzleHttp\Event\Event`, and Guzzle now has an EventInterface in |
|
275 |
`GuzzleHttp\Event\EventInterface`. |
|
276 |
- `AbstractHasDispatcher` has moved to a trait, `HasEmitterTrait`, and |
|
277 |
`HasDispatcherInterface` has moved to `HasEmitterInterface`. Retrieving the |
|
278 |
event emitter of a request, client, etc. now uses the `getEmitter` method |
|
279 |
rather than the `getDispatcher` method. |
|
280 |
|
|
281 |
#### Emitter |
|
282 |
|
|
283 |
- Use the `once()` method to add a listener that automatically removes itself |
|
284 |
the first time it is invoked. |
|
285 |
- Use the `listeners()` method to retrieve a list of event listeners rather than |
|
286 |
the `getListeners()` method. |
|
287 |
- Use `emit()` instead of `dispatch()` to emit an event from an emitter. |
|
288 |
- Use `attach()` instead of `addSubscriber()` and `detach()` instead of |
|
289 |
`removeSubscriber()`. |
|
290 |
|
|
291 |
```php |
|
292 |
$mock = new Mock(); |
|
293 |
// 3.x |
|
294 |
$request->getEventDispatcher()->addSubscriber($mock); |
|
295 |
$request->getEventDispatcher()->removeSubscriber($mock); |
|
296 |
// 4.x |
|
297 |
$request->getEmitter()->attach($mock); |
|
298 |
$request->getEmitter()->detach($mock); |
|
299 |
``` |
|
300 |
|
|
301 |
Use the `on()` method to add a listener rather than the `addListener()` method. |
|
302 |
|
|
303 |
```php |
|
304 |
// 3.x |
|
305 |
$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } ); |
|
306 |
// 4.x |
|
307 |
$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } ); |
|
308 |
``` |
|
309 |
|
|
310 |
## Http |
|
311 |
|
|
312 |
### General changes |
|
313 |
|
|
314 |
- The cacert.pem certificate has been moved to `src/cacert.pem`. |
|
315 |
- Added the concept of adapters that are used to transfer requests over the |
|
316 |
wire. |
|
317 |
- Simplified the event system. |
|
318 |
- Sending requests in parallel is still possible, but batching is no longer a |
|
319 |
concept of the HTTP layer. Instead, you must use the `complete` and `error` |
|
320 |
events to asynchronously manage parallel request transfers. |
|
321 |
- `Guzzle\Http\Url` has moved to `GuzzleHttp\Url`. |
|
322 |
- `Guzzle\Http\QueryString` has moved to `GuzzleHttp\Query`. |
|
323 |
- QueryAggregators have been rewritten so that they are simply callable |
|
324 |
functions. |
|
325 |
- `GuzzleHttp\StaticClient` has been removed. Use the functions provided in |
|
326 |
`functions.php` for an easy to use static client instance. |
|
327 |
- Exceptions in `GuzzleHttp\Exception` have been updated to all extend from |
|
328 |
`GuzzleHttp\Exception\TransferException`. |
|
329 |
|
|
330 |
### Client |
|
331 |
|
|
332 |
Calling methods like `get()`, `post()`, `head()`, etc. no longer create and |
|
333 |
return a request, but rather creates a request, sends the request, and returns |
|
334 |
the response. |
|
335 |
|
|
336 |
```php |
|
337 |
// 3.0 |
|
338 |
$request = $client->get('/'); |
|
339 |
$response = $request->send(); |
|
340 |
|
|
341 |
// 4.0 |
|
342 |
$response = $client->get('/'); |
|
343 |
|
|
344 |
// or, to mirror the previous behavior |
|
345 |
$request = $client->createRequest('GET', '/'); |
|
346 |
$response = $client->send($request); |
|
347 |
``` |
|
348 |
|
|
349 |
`GuzzleHttp\ClientInterface` has changed. |
|
350 |
|
|
351 |
- The `send` method no longer accepts more than one request. Use `sendAll` to |
|
352 |
send multiple requests in parallel. |
|
353 |
- `setUserAgent()` has been removed. Use a default request option instead. You |
|
354 |
could, for example, do something like: |
|
355 |
`$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())`. |
|
356 |
- `setSslVerification()` has been removed. Use default request options instead, |
|
357 |
like `$client->setConfig('defaults/verify', true)`. |
|
358 |
|
|
359 |
`GuzzleHttp\Client` has changed. |
|
360 |
|
|
361 |
- The constructor now accepts only an associative array. You can include a |
|
362 |
`base_url` string or array to use a URI template as the base URL of a client. |
|
363 |
You can also specify a `defaults` key that is an associative array of default |
|
364 |
request options. You can pass an `adapter` to use a custom adapter, |
|
365 |
`batch_adapter` to use a custom adapter for sending requests in parallel, or |
|
366 |
a `message_factory` to change the factory used to create HTTP requests and |
|
367 |
responses. |
|
368 |
- The client no longer emits a `client.create_request` event. |
|
369 |
- Creating requests with a client no longer automatically utilize a URI |
|
370 |
template. You must pass an array into a creational method (e.g., |
|
371 |
`createRequest`, `get`, `put`, etc.) in order to expand a URI template. |
|
372 |
|
|
373 |
### Messages |
|
374 |
|
|
375 |
Messages no longer have references to their counterparts (i.e., a request no |
|
376 |
longer has a reference to it's response, and a response no loger has a |
|
377 |
reference to its request). This association is now managed through a |
|
378 |
`GuzzleHttp\Adapter\TransactionInterface` object. You can get references to |
|
379 |
these transaction objects using request events that are emitted over the |
|
380 |
lifecycle of a request. |
|
381 |
|
|
382 |
#### Requests with a body |
|
383 |
|
|
384 |
- `GuzzleHttp\Message\EntityEnclosingRequest` and |
|
385 |
`GuzzleHttp\Message\EntityEnclosingRequestInterface` have been removed. The |
|
386 |
separation between requests that contain a body and requests that do not |
|
387 |
contain a body has been removed, and now `GuzzleHttp\Message\RequestInterface` |
|
388 |
handles both use cases. |
|
389 |
- Any method that previously accepts a `GuzzleHttp\Response` object now accept a |
|
390 |
`GuzzleHttp\Message\ResponseInterface`. |
|
391 |
- `GuzzleHttp\Message\RequestFactoryInterface` has been renamed to |
|
392 |
`GuzzleHttp\Message\MessageFactoryInterface`. This interface is used to create |
|
393 |
both requests and responses and is implemented in |
|
394 |
`GuzzleHttp\Message\MessageFactory`. |
|
395 |
- POST field and file methods have been removed from the request object. You |
|
396 |
must now use the methods made available to `GuzzleHttp\Post\PostBodyInterface` |
|
397 |
to control the format of a POST body. Requests that are created using a |
|
398 |
standard `GuzzleHttp\Message\MessageFactoryInterface` will automatically use |
|
399 |
a `GuzzleHttp\Post\PostBody` body if the body was passed as an array or if |
|
400 |
the method is POST and no body is provided. |
|
401 |
|
|
402 |
```php |
|
403 |
$request = $client->createRequest('POST', '/'); |
|
404 |
$request->getBody()->setField('foo', 'bar'); |
|
405 |
$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r'))); |
|
406 |
``` |
|
407 |
|
|
408 |
#### Headers |
|
409 |
|
|
410 |
- `GuzzleHttp\Message\Header` has been removed. Header values are now simply |
|
411 |
represented by an array of values or as a string. Header values are returned |
|
412 |
as a string by default when retrieving a header value from a message. You can |
|
413 |
pass an optional argument of `true` to retrieve a header value as an array |
|
414 |
of strings instead of a single concatenated string. |
|
415 |
- `GuzzleHttp\PostFile` and `GuzzleHttp\PostFileInterface` have been moved to |
|
416 |
`GuzzleHttp\Post`. This interface has been simplified and now allows the |
|
417 |
addition of arbitrary headers. |
|
418 |
- Custom headers like `GuzzleHttp\Message\Header\Link` have been removed. Most |
|
419 |
of the custom headers are now handled separately in specific |
|
420 |
subscribers/plugins, and `GuzzleHttp\Message\HeaderValues::parseParams()` has |
|
421 |
been updated to properly handle headers that contain parameters (like the |
|
422 |
`Link` header). |
|
423 |
|
|
424 |
#### Responses |
|
425 |
|
|
426 |
- `GuzzleHttp\Message\Response::getInfo()` and |
|
427 |
`GuzzleHttp\Message\Response::setInfo()` have been removed. Use the event |
|
428 |
system to retrieve this type of information. |
|
429 |
- `GuzzleHttp\Message\Response::getRawHeaders()` has been removed. |
|
430 |
- `GuzzleHttp\Message\Response::getMessage()` has been removed. |
|
431 |
- `GuzzleHttp\Message\Response::calculateAge()` and other cache specific |
|
432 |
methods have moved to the CacheSubscriber. |
|
433 |
- Header specific helper functions like `getContentMd5()` have been removed. |
|
434 |
Just use `getHeader('Content-MD5')` instead. |
|
435 |
- `GuzzleHttp\Message\Response::setRequest()` and |
|
436 |
`GuzzleHttp\Message\Response::getRequest()` have been removed. Use the event |
|
437 |
system to work with request and response objects as a transaction. |
|
438 |
- `GuzzleHttp\Message\Response::getRedirectCount()` has been removed. Use the |
|
439 |
Redirect subscriber instead. |
|
440 |
- `GuzzleHttp\Message\Response::isSuccessful()` and other related methods have |
|
441 |
been removed. Use `getStatusCode()` instead. |
|
442 |
|
|
443 |
#### Streaming responses |
|
444 |
|
|
445 |
Streaming requests can now be created by a client directly, returning a |
|
446 |
`GuzzleHttp\Message\ResponseInterface` object that contains a body stream |
|
447 |
referencing an open PHP HTTP stream. |
|
448 |
|
|
449 |
```php |
|
450 |
// 3.0 |
|
451 |
use Guzzle\Stream\PhpStreamRequestFactory; |
|
452 |
$request = $client->get('/'); |
|
453 |
$factory = new PhpStreamRequestFactory(); |
|
454 |
$stream = $factory->fromRequest($request); |
|
455 |
$data = $stream->read(1024); |
|
456 |
|
|
457 |
// 4.0 |
|
458 |
$response = $client->get('/', ['stream' => true]); |
|
459 |
// Read some data off of the stream in the response body |
|
460 |
$data = $response->getBody()->read(1024); |
|
461 |
``` |
|
462 |
|
|
463 |
#### Redirects |
|
464 |
|
|
465 |
The `configureRedirects()` method has been removed in favor of a |
|
466 |
`allow_redirects` request option. |
|
467 |
|
|
468 |
```php |
|
469 |
// Standard redirects with a default of a max of 5 redirects |
|
470 |
$request = $client->createRequest('GET', '/', ['allow_redirects' => true]); |
|
471 |
|
|
472 |
// Strict redirects with a custom number of redirects |
|
473 |
$request = $client->createRequest('GET', '/', [ |
|
474 |
'allow_redirects' => ['max' => 5, 'strict' => true] |
|
475 |
]); |
|
476 |
``` |
|
477 |
|
|
478 |
#### EntityBody |
|
479 |
|
|
480 |
EntityBody interfaces and classes have been removed or moved to |
|
481 |
`GuzzleHttp\Stream`. All classes and interfaces that once required |
|
482 |
`GuzzleHttp\EntityBodyInterface` now require |
|
483 |
`GuzzleHttp\Stream\StreamInterface`. Creating a new body for a request no |
|
484 |
longer uses `GuzzleHttp\EntityBody::factory` but now uses |
|
485 |
`GuzzleHttp\Stream\Stream::factory` or even better: |
|
486 |
`GuzzleHttp\Stream\create()`. |
|
487 |
|
|
488 |
- `Guzzle\Http\EntityBodyInterface` is now `GuzzleHttp\Stream\StreamInterface` |
|
489 |
- `Guzzle\Http\EntityBody` is now `GuzzleHttp\Stream\Stream` |
|
490 |
- `Guzzle\Http\CachingEntityBody` is now `GuzzleHttp\Stream\CachingStream` |
|
491 |
- `Guzzle\Http\ReadLimitEntityBody` is now `GuzzleHttp\Stream\LimitStream` |
|
492 |
- `Guzzle\Http\IoEmittyinEntityBody` has been removed. |
|
493 |
|
|
494 |
#### Request lifecycle events |
|
495 |
|
|
496 |
Requests previously submitted a large number of requests. The number of events |
|
497 |
emitted over the lifecycle of a request has been significantly reduced to make |
|
498 |
it easier to understand how to extend the behavior of a request. All events |
|
499 |
emitted during the lifecycle of a request now emit a custom |
|
500 |
`GuzzleHttp\Event\EventInterface` object that contains context providing |
|
501 |
methods and a way in which to modify the transaction at that specific point in |
|
502 |
time (e.g., intercept the request and set a response on the transaction). |
|
503 |
|
|
504 |
- `request.before_send` has been renamed to `before` and now emits a |
|
505 |
`GuzzleHttp\Event\BeforeEvent` |
|
506 |
- `request.complete` has been renamed to `complete` and now emits a |
|
507 |
`GuzzleHttp\Event\CompleteEvent`. |
|
508 |
- `request.sent` has been removed. Use `complete`. |
|
509 |
- `request.success` has been removed. Use `complete`. |
|
510 |
- `error` is now an event that emits a `GuzzleHttp\Event\ErrorEvent`. |
|
511 |
- `request.exception` has been removed. Use `error`. |
|
512 |
- `request.receive.status_line` has been removed. |
|
513 |
- `curl.callback.progress` has been removed. Use a custom `StreamInterface` to |
|
514 |
maintain a status update. |
|
515 |
- `curl.callback.write` has been removed. Use a custom `StreamInterface` to |
|
516 |
intercept writes. |
|
517 |
- `curl.callback.read` has been removed. Use a custom `StreamInterface` to |
|
518 |
intercept reads. |
|
519 |
|
|
520 |
`headers` is a new event that is emitted after the response headers of a |
|
521 |
request have been received before the body of the response is downloaded. This |
|
522 |
event emits a `GuzzleHttp\Event\HeadersEvent`. |
|
523 |
|
|
524 |
You can intercept a request and inject a response using the `intercept()` event |
|
525 |
of a `GuzzleHttp\Event\BeforeEvent`, `GuzzleHttp\Event\CompleteEvent`, and |
|
526 |
`GuzzleHttp\Event\ErrorEvent` event. |
|
527 |
|
|
528 |
See: http://docs.guzzlephp.org/en/latest/events.html |
|
529 |
|
|
530 |
## Inflection |
|
531 |
|
|
532 |
The `Guzzle\Inflection` namespace has been removed. This is not a core concern |
|
533 |
of Guzzle. |
|
534 |
|
|
535 |
## Iterator |
|
536 |
|
|
537 |
The `Guzzle\Iterator` namespace has been removed. |
|
538 |
|
|
539 |
- `Guzzle\Iterator\AppendIterator`, `Guzzle\Iterator\ChunkedIterator`, and |
|
540 |
`Guzzle\Iterator\MethodProxyIterator` are nice, but not a core requirement of |
|
541 |
Guzzle itself. |
|
542 |
- `Guzzle\Iterator\FilterIterator` is no longer needed because an equivalent |
|
543 |
class is shipped with PHP 5.4. |
|
544 |
- `Guzzle\Iterator\MapIterator` is not really needed when using PHP 5.5 because |
|
545 |
it's easier to just wrap an iterator in a generator that maps values. |
|
546 |
|
|
547 |
For a replacement of these iterators, see https://github.com/nikic/iter |
|
548 |
|
|
549 |
## Log |
|
550 |
|
|
551 |
The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The |
|
552 |
`Guzzle\Log` namespace has been removed. Guzzle now relies on |
|
553 |
`Psr\Log\LoggerInterface` for all logging. The MessageFormatter class has been |
|
554 |
moved to `GuzzleHttp\Subscriber\Log\Formatter`. |
|
555 |
|
|
556 |
## Parser |
|
557 |
|
|
558 |
The `Guzzle\Parser` namespace has been removed. This was previously used to |
|
559 |
make it possible to plug in custom parsers for cookies, messages, URI |
|
560 |
templates, and URLs; however, this level of complexity is not needed in Guzzle |
|
561 |
so it has been removed. |
|
562 |
|
|
563 |
- Cookie: Cookie parsing logic has been moved to |
|
564 |
`GuzzleHttp\Cookie\SetCookie::fromString`. |
|
565 |
- Message: Message parsing logic for both requests and responses has been moved |
|
566 |
to `GuzzleHttp\Message\MessageFactory::fromMessage`. Message parsing is only |
|
567 |
used in debugging or deserializing messages, so it doesn't make sense for |
|
568 |
Guzzle as a library to add this level of complexity to parsing messages. |
|
569 |
- UriTemplate: URI template parsing has been moved to |
|
570 |
`GuzzleHttp\UriTemplate`. The Guzzle library will automatically use the PECL |
|
571 |
URI template library if it is installed. |
|
572 |
- Url: URL parsing is now performed in `GuzzleHttp\Url::fromString` (previously |
|
573 |
it was `Guzzle\Http\Url::factory()`). If custom URL parsing is necessary, |
|
574 |
then developers are free to subclass `GuzzleHttp\Url`. |
|
575 |
|
|
576 |
## Plugin |
|
577 |
|
|
578 |
The `Guzzle\Plugin` namespace has been renamed to `GuzzleHttp\Subscriber`. |
|
579 |
Several plugins are shipping with the core Guzzle library under this namespace. |
|
580 |
|
|
581 |
- `GuzzleHttp\Subscriber\Cookie`: Replaces the old CookiePlugin. Cookie jar |
|
582 |
code has moved to `GuzzleHttp\Cookie`. |
|
583 |
- `GuzzleHttp\Subscriber\History`: Replaces the old HistoryPlugin. |
|
584 |
- `GuzzleHttp\Subscriber\HttpError`: Throws errors when a bad HTTP response is |
|
585 |
received. |
|
586 |
- `GuzzleHttp\Subscriber\Mock`: Replaces the old MockPlugin. |
|
587 |
- `GuzzleHttp\Subscriber\Prepare`: Prepares the body of a request just before |
|
588 |
sending. This subscriber is attached to all requests by default. |
|
589 |
- `GuzzleHttp\Subscriber\Redirect`: Replaces the RedirectPlugin. |
|
590 |
|
|
591 |
The following plugins have been removed (third-parties are free to re-implement |
|
592 |
these if needed): |
|
593 |
|
|
594 |
- `GuzzleHttp\Plugin\Async` has been removed. |
|
595 |
- `GuzzleHttp\Plugin\CurlAuth` has been removed. |
|
596 |
- `GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin` has been removed. This |
|
597 |
functionality should instead be implemented with event listeners that occur |
|
598 |
after normal response parsing occurs in the guzzle/command package. |
|
599 |
|
|
600 |
The following plugins are not part of the core Guzzle package, but are provided |
|
601 |
in separate repositories: |
|
602 |
|
|
603 |
- `Guzzle\Http\Plugin\BackoffPlugin` has been rewritten to be much simpler |
|
604 |
to build custom retry policies using simple functions rather than various |
|
605 |
chained classes. See: https://github.com/guzzle/retry-subscriber |
|
606 |
- `Guzzle\Http\Plugin\Cache\CachePlugin` has moved to |
|
607 |
https://github.com/guzzle/cache-subscriber |
|
608 |
- `Guzzle\Http\Plugin\Log\LogPlugin` has moved to |
|
609 |
https://github.com/guzzle/log-subscriber |
|
610 |
- `Guzzle\Http\Plugin\Md5\Md5Plugin` has moved to |
|
611 |
https://github.com/guzzle/message-integrity-subscriber |
|
612 |
- `Guzzle\Http\Plugin\Mock\MockPlugin` has moved to |
|
613 |
`GuzzleHttp\Subscriber\MockSubscriber`. |
|
614 |
- `Guzzle\Http\Plugin\Oauth\OauthPlugin` has moved to |
|
615 |
https://github.com/guzzle/oauth-subscriber |
|
616 |
|
|
617 |
## Service |
|
618 |
|
|
619 |
The service description layer of Guzzle has moved into two separate packages: |
|
620 |
|
|
621 |
- http://github.com/guzzle/command Provides a high level abstraction over web |
|
622 |
services by representing web service operations using commands. |
|
623 |
- http://github.com/guzzle/guzzle-services Provides an implementation of |
|
624 |
guzzle/command that provides request serialization and response parsing using |
|
625 |
Guzzle service descriptions. |
|
626 |
|
|
627 |
## Stream |
|
628 |
|
|
629 |
Stream have moved to a separate package available at |
|
630 |
https://github.com/guzzle/streams. |
|
631 |
|
|
632 |
`Guzzle\Stream\StreamInterface` has been given a large update to cleanly take |
|
633 |
on the responsibilities of `Guzzle\Http\EntityBody` and |
|
634 |
`Guzzle\Http\EntityBodyInterface` now that they have been removed. The number |
|
635 |
of methods implemented by the `StreamInterface` has been drastically reduced to |
|
636 |
allow developers to more easily extend and decorate stream behavior. |
|
637 |
|
|
638 |
## Removed methods from StreamInterface |
|
639 |
|
|
640 |
- `getStream` and `setStream` have been removed to better encapsulate streams. |
|
641 |
- `getMetadata` and `setMetadata` have been removed in favor of |
|
642 |
`GuzzleHttp\Stream\MetadataStreamInterface`. |
|
643 |
- `getWrapper`, `getWrapperData`, `getStreamType`, and `getUri` have all been |
|
644 |
removed. This data is accessible when |
|
645 |
using streams that implement `GuzzleHttp\Stream\MetadataStreamInterface`. |
|
646 |
- `rewind` has been removed. Use `seek(0)` for a similar behavior. |
|
647 |
|
|
648 |
## Renamed methods |
|
649 |
|
|
650 |
- `detachStream` has been renamed to `detach`. |
|
651 |
- `feof` has been renamed to `eof`. |
|
652 |
- `ftell` has been renamed to `tell`. |
|
653 |
- `readLine` has moved from an instance method to a static class method of |
|
654 |
`GuzzleHttp\Stream\Stream`. |
|
655 |
|
|
656 |
## Metadata streams |
|
657 |
|
|
658 |
`GuzzleHttp\Stream\MetadataStreamInterface` has been added to denote streams |
|
659 |
that contain additional metadata accessible via `getMetadata()`. |
|
660 |
`GuzzleHttp\Stream\StreamInterface::getMetadata` and |
|
661 |
`GuzzleHttp\Stream\StreamInterface::setMetadata` have been removed. |
|
662 |
|
|
663 |
## StreamRequestFactory |
|
664 |
|
|
665 |
The entire concept of the StreamRequestFactory has been removed. The way this |
|
666 |
was used in Guzzle 3 broke the actual interface of sending streaming requests |
|
667 |
(instead of getting back a Response, you got a StreamInterface). Streaming |
|
668 |
PHP requests are now implemented through the `GuzzleHttp\Adapter\StreamAdapter`. |
|
669 |
|
|
670 |
3.6 to 3.7 |
|
671 |
---------- |
|
672 |
|
|
673 |
### Deprecations |
|
674 |
|
|
675 |
- You can now enable E_USER_DEPRECATED warnings to see if you are using any deprecated methods.: |
|
676 |
|
|
677 |
```php |
|
678 |
\Guzzle\Common\Version::$emitWarnings = true; |
|
679 |
``` |
|
680 |
|
|
681 |
The following APIs and options have been marked as deprecated: |
|
682 |
|
|
683 |
- Marked `Guzzle\Http\Message\Request::isResponseBodyRepeatable()` as deprecated. Use `$request->getResponseBody()->isRepeatable()` instead. |
|
684 |
- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. |
|
685 |
- Marked `Guzzle\Http\Message\Request::canCache()` as deprecated. Use `Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()` instead. |
|
686 |
- Marked `Guzzle\Http\Message\Request::setIsRedirect()` as deprecated. Use the HistoryPlugin instead. |
|
687 |
- Marked `Guzzle\Http\Message\Request::isRedirect()` as deprecated. Use the HistoryPlugin instead. |
|
688 |
- Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated |
|
689 |
- Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client. |
|
690 |
- Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8. |
|
691 |
- Marked `Guzzle\Common\Collection::inject()` as deprecated. |
|
692 |
- Marked `Guzzle\Plugin\CurlAuth\CurlAuthPlugin` as deprecated. Use |
|
693 |
`$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` or |
|
694 |
`$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));` |
|
695 |
|
|
696 |
3.7 introduces `request.options` as a parameter for a client configuration and as an optional argument to all creational |
|
697 |
request methods. When paired with a client's configuration settings, these options allow you to specify default settings |
|
698 |
for various aspects of a request. Because these options make other previous configuration options redundant, several |
|
699 |
configuration options and methods of a client and AbstractCommand have been deprecated. |
|
700 |
|
|
701 |
- Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use `$client->getDefaultOption('headers')`. |
|
702 |
- Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use `$client->setDefaultOption('headers/{header_name}', 'value')`. |
|
703 |
- Marked 'request.params' for `Guzzle\Http\Client` as deprecated. Use `$client->setDefaultOption('params/{param_name}', 'value')` |
|
704 |
- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0 |
|
705 |
|
|
706 |
$command = $client->getCommand('foo', array( |
|
707 |
'command.headers' => array('Test' => '123'), |
|
708 |
'command.response_body' => '/path/to/file' |
|
709 |
)); |
|
710 |
|
|
711 |
// Should be changed to: |
|
712 |
|
|
713 |
$command = $client->getCommand('foo', array( |
|
714 |
'command.request_options' => array( |
|
715 |
'headers' => array('Test' => '123'), |
|
716 |
'save_as' => '/path/to/file' |
|
717 |
) |
|
718 |
)); |
|
719 |
|
|
720 |
### Interface changes |
|
721 |
|
|
722 |
Additions and changes (you will need to update any implementations or subclasses you may have created): |
|
723 |
|
|
724 |
- Added an `$options` argument to the end of the following methods of `Guzzle\Http\ClientInterface`: |
|
725 |
createRequest, head, delete, put, patch, post, options, prepareRequest |
|
726 |
- Added an `$options` argument to the end of `Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()` |
|
727 |
- Added an `applyOptions()` method to `Guzzle\Http\Message\Request\RequestFactoryInterface` |
|
728 |
- Changed `Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)` to |
|
729 |
`Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())`. You can still pass in a |
|
730 |
resource, string, or EntityBody into the $options parameter to specify the download location of the response. |
|
731 |
- Changed `Guzzle\Common\Collection::__construct($data)` to no longer accepts a null value for `$data` but a |
|
732 |
default `array()` |
|
733 |
- Added `Guzzle\Stream\StreamInterface::isRepeatable` |
|
734 |
- Made `Guzzle\Http\Client::expandTemplate` and `getUriTemplate` protected methods. |
|
735 |
|
|
736 |
The following methods were removed from interfaces. All of these methods are still available in the concrete classes |
|
737 |
that implement them, but you should update your code to use alternative methods: |
|
738 |
|
|
739 |
- Removed `Guzzle\Http\ClientInterface::setDefaultHeaders(). Use |
|
740 |
`$client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`. or |
|
741 |
`$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))` or |
|
742 |
`$client->setDefaultOption('headers/{header_name}', 'value')`. or |
|
743 |
`$client->setDefaultOption('headers', array('header_name' => 'value'))`. |
|
744 |
- Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use `$client->getConfig()->getPath('request.options/headers')`. |
|
745 |
- Removed `Guzzle\Http\ClientInterface::expandTemplate()`. This is an implementation detail. |
|
746 |
- Removed `Guzzle\Http\ClientInterface::setRequestFactory()`. This is an implementation detail. |
|
747 |
- Removed `Guzzle\Http\ClientInterface::getCurlMulti()`. This is a very specific implementation detail. |
|
748 |
- Removed `Guzzle\Http\Message\RequestInterface::canCache`. Use the CachePlugin. |
|
749 |
- Removed `Guzzle\Http\Message\RequestInterface::setIsRedirect`. Use the HistoryPlugin. |
|
750 |
- Removed `Guzzle\Http\Message\RequestInterface::isRedirect`. Use the HistoryPlugin. |
|
751 |
|
|
752 |
### Cache plugin breaking changes |
|
753 |
|
|
754 |
- CacheKeyProviderInterface and DefaultCacheKeyProvider are no longer used. All of this logic is handled in a |
|
755 |
CacheStorageInterface. These two objects and interface will be removed in a future version. |
|
756 |
- Always setting X-cache headers on cached responses |
|
757 |
- Default cache TTLs are now handled by the CacheStorageInterface of a CachePlugin |
|
758 |
- `CacheStorageInterface::cache($key, Response $response, $ttl = null)` has changed to `cache(RequestInterface |
|
759 |
$request, Response $response);` |
|
760 |
- `CacheStorageInterface::fetch($key)` has changed to `fetch(RequestInterface $request);` |
|
761 |
- `CacheStorageInterface::delete($key)` has changed to `delete(RequestInterface $request);` |
|
762 |
- Added `CacheStorageInterface::purge($url)` |
|
763 |
- `DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin |
|
764 |
$plugin)` has changed to `DefaultRevalidation::__construct(CacheStorageInterface $cache, |
|
765 |
CanCacheStrategyInterface $canCache = null)` |
|
766 |
- Added `RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)` |
|
767 |
|
|
768 |
3.5 to 3.6 |
|
769 |
---------- |
|
770 |
|
|
771 |
* Mixed casing of headers are now forced to be a single consistent casing across all values for that header. |
|
772 |
* Messages internally use a HeaderCollection object to delegate handling case-insensitive header resolution |
|
773 |
* Removed the whole changedHeader() function system of messages because all header changes now go through addHeader(). |
|
774 |
For example, setHeader() first removes the header using unset on a HeaderCollection and then calls addHeader(). |
|
775 |
Keeping the Host header and URL host in sync is now handled by overriding the addHeader method in Request. |
|
776 |
* Specific header implementations can be created for complex headers. When a message creates a header, it uses a |
|
777 |
HeaderFactory which can map specific headers to specific header classes. There is now a Link header and |
|
778 |
CacheControl header implementation. |
|
779 |
* Moved getLinks() from Response to just be used on a Link header object. |
|
780 |
|
|
781 |
If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the |
|
782 |
HeaderInterface (e.g. toArray(), getAll(), etc.). |
|
783 |
|
|
784 |
### Interface changes |
|
785 |
|
|
786 |
* Removed from interface: Guzzle\Http\ClientInterface::setUriTemplate |
|
787 |
* Removed from interface: Guzzle\Http\ClientInterface::setCurlMulti() |
|
788 |
* Removed Guzzle\Http\Message\Request::receivedRequestHeader() and implemented this functionality in |
|
789 |
Guzzle\Http\Curl\RequestMediator |
|
790 |
* Removed the optional $asString parameter from MessageInterface::getHeader(). Just cast the header to a string. |
|
791 |
* Removed the optional $tryChunkedTransfer option from Guzzle\Http\Message\EntityEnclosingRequestInterface |
|
792 |
* Removed the $asObjects argument from Guzzle\Http\Message\MessageInterface::getHeaders() |
|
793 |
|
|
794 |
### Removed deprecated functions |
|
795 |
|
|
796 |
* Removed Guzzle\Parser\ParserRegister::get(). Use getParser() |
|
797 |
* Removed Guzzle\Parser\ParserRegister::set(). Use registerParser(). |
|
798 |
|
|
799 |
### Deprecations |
|
800 |
|
|
801 |
* The ability to case-insensitively search for header values |
|
802 |
* Guzzle\Http\Message\Header::hasExactHeader |
|
803 |
* Guzzle\Http\Message\Header::raw. Use getAll() |
|
804 |
* Deprecated cache control specific methods on Guzzle\Http\Message\AbstractMessage. Use the CacheControl header object |
|
805 |
instead. |
|
806 |
|
|
807 |
### Other changes |
|
808 |
|
|
809 |
* All response header helper functions return a string rather than mixing Header objects and strings inconsistently |
|
810 |
* Removed cURL blacklist support. This is no longer necessary now that Expect, Accept, etc. are managed by Guzzle |
|
811 |
directly via interfaces |
|
812 |
* Removed the injecting of a request object onto a response object. The methods to get and set a request still exist |
|
813 |
but are a no-op until removed. |
|
814 |
* Most classes that used to require a `Guzzle\Service\Command\CommandInterface` typehint now request a |
|
815 |
`Guzzle\Service\Command\ArrayCommandInterface`. |
|
816 |
* Added `Guzzle\Http\Message\RequestInterface::startResponse()` to the RequestInterface to handle injecting a response |
|
817 |
on a request while the request is still being transferred |
|
818 |
* `Guzzle\Service\Command\CommandInterface` now extends from ToArrayInterface and ArrayAccess |
|
819 |
|
|
820 |
3.3 to 3.4 |
|
821 |
---------- |
|
822 |
|
|
823 |
Base URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs. |
|
824 |
|
|
825 |
3.2 to 3.3 |
|
826 |
---------- |
|
827 |
|
|
828 |
### Response::getEtag() quote stripping removed |
|
829 |
|
|
830 |
`Guzzle\Http\Message\Response::getEtag()` no longer strips quotes around the ETag response header |
|
831 |
|
|
832 |
### Removed `Guzzle\Http\Utils` |
|
833 |
|
|
834 |
The `Guzzle\Http\Utils` class was removed. This class was only used for testing. |
|
835 |
|
|
836 |
### Stream wrapper and type |
|
837 |
|
|
838 |
`Guzzle\Stream\Stream::getWrapper()` and `Guzzle\Stream\Stream::getStreamType()` are no longer converted to lowercase. |
|
839 |
|
|
840 |
### curl.emit_io became emit_io |
|
841 |
|
|
842 |
Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the |
|
843 |
'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io' |
|
844 |
|
|
845 |
3.1 to 3.2 |
|
846 |
---------- |
|
847 |
|
|
848 |
### CurlMulti is no longer reused globally |
|
849 |
|
|
850 |
Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added |
|
851 |
to a single client can pollute requests dispatched from other clients. |
|
852 |
|
|
853 |
If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the |
|
854 |
ServiceBuilder's `service_builder.create_client` event to inject a custom CurlMulti object into each client as it is |
|
855 |
created. |
|
856 |
|
|
857 |
```php |
|
858 |
$multi = new Guzzle\Http\Curl\CurlMulti(); |
|
859 |
$builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json'); |
|
860 |
$builder->addListener('service_builder.create_client', function ($event) use ($multi) { |
|
861 |
$event['client']->setCurlMulti($multi); |
|
862 |
} |
|
863 |
}); |
|
864 |
``` |
|
865 |
|
|
866 |
### No default path |
|
867 |
|
|
868 |
URLs no longer have a default path value of '/' if no path was specified. |
|
869 |
|
|
870 |
Before: |
|
871 |
|
|
872 |
```php |
|
873 |
$request = $client->get('http://www.foo.com'); |
|
874 |
echo $request->getUrl(); |
|
875 |
// >> http://www.foo.com/ |
|
876 |
``` |
|
877 |
|
|
878 |
After: |
|
879 |
|
|
880 |
```php |
|
881 |
$request = $client->get('http://www.foo.com'); |
|
882 |
echo $request->getUrl(); |
|
883 |
// >> http://www.foo.com |
|
884 |
``` |
|
885 |
|
|
886 |
### Less verbose BadResponseException |
|
887 |
|
|
888 |
The exception message for `Guzzle\Http\Exception\BadResponseException` no longer contains the full HTTP request and |
|
889 |
response information. You can, however, get access to the request and response object by calling `getRequest()` or |
|
890 |
`getResponse()` on the exception object. |
|
891 |
|
|
892 |
### Query parameter aggregation |
|
893 |
|
|
894 |
Multi-valued query parameters are no longer aggregated using a callback function. `Guzzle\Http\Query` now has a |
|
895 |
setAggregator() method that accepts a `Guzzle\Http\QueryAggregator\QueryAggregatorInterface` object. This object is |
|
896 |
responsible for handling the aggregation of multi-valued query string variables into a flattened hash. |
|
897 |
|
|
898 |
2.8 to 3.x |
|
899 |
---------- |
|
900 |
|
|
901 |
### Guzzle\Service\Inspector |
|
902 |
|
|
903 |
Change `\Guzzle\Service\Inspector::fromConfig` to `\Guzzle\Common\Collection::fromConfig` |
|
904 |
|
|
905 |
**Before** |
|
906 |
|
|
907 |
```php |
|
908 |
use Guzzle\Service\Inspector; |
|
909 |
|
|
910 |
class YourClient extends \Guzzle\Service\Client |
|
911 |
{ |
|
912 |
public static function factory($config = array()) |
|
913 |
{ |
|
914 |
$default = array(); |
|
915 |
$required = array('base_url', 'username', 'api_key'); |
|
916 |
$config = Inspector::fromConfig($config, $default, $required); |
|
917 |
|
|
918 |
$client = new self( |
|
919 |
$config->get('base_url'), |
|
920 |
$config->get('username'), |
|
921 |
$config->get('api_key') |
|
922 |
); |
|
923 |
$client->setConfig($config); |
|
924 |
|
|
925 |
$client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json')); |
|
926 |
|
|
927 |
return $client; |
|
928 |
} |
|
929 |
``` |
|
930 |
|
|
931 |
**After** |
|
932 |
|
|
933 |
```php |
|
934 |
use Guzzle\Common\Collection; |
|
935 |
|
|
936 |
class YourClient extends \Guzzle\Service\Client |
|
937 |
{ |
|
938 |
public static function factory($config = array()) |
|
939 |
{ |
|
940 |
$default = array(); |
|
941 |
$required = array('base_url', 'username', 'api_key'); |
|
942 |
$config = Collection::fromConfig($config, $default, $required); |
|
943 |
|
|
944 |
$client = new self( |
|
945 |
$config->get('base_url'), |
|
946 |
$config->get('username'), |
|
947 |
$config->get('api_key') |
|
948 |
); |
|
949 |
$client->setConfig($config); |
|
950 |
|
|
951 |
$client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json')); |
|
952 |
|
|
953 |
return $client; |
|
954 |
} |
|
955 |
``` |
|
956 |
|
|
957 |
### Convert XML Service Descriptions to JSON |
|
958 |
|
|
959 |
**Before** |
|
960 |
|
|
961 |
```xml |
|
962 |
<?xml version="1.0" encoding="UTF-8"?> |
|
963 |
<client> |
|
964 |
<commands> |
|
965 |
<!-- Groups --> |
|
966 |
<command name="list_groups" method="GET" uri="groups.json"> |
|
967 |
<doc>Get a list of groups</doc> |
|
968 |
</command> |
|
969 |
<command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'> |
|
970 |
<doc>Uses a search query to get a list of groups</doc> |
|
971 |
<param name="query" type="string" required="true" /> |
|
972 |
</command> |
|
973 |
<command name="create_group" method="POST" uri="groups.json"> |
|
974 |
<doc>Create a group</doc> |
|
975 |
<param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/> |
|
976 |
<param name="Content-Type" location="header" static="application/json"/> |
|
977 |
</command> |
|
978 |
<command name="delete_group" method="DELETE" uri="groups/{{id}}.json"> |
|
979 |
<doc>Delete a group by ID</doc> |
|
980 |
<param name="id" type="integer" required="true"/> |
|
981 |
</command> |
|
982 |
<command name="get_group" method="GET" uri="groups/{{id}}.json"> |
|
983 |
<param name="id" type="integer" required="true"/> |
|
984 |
</command> |
|
985 |
<command name="update_group" method="PUT" uri="groups/{{id}}.json"> |
|
986 |
<doc>Update a group</doc> |
|
987 |
<param name="id" type="integer" required="true"/> |
|
988 |
<param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/> |
|
989 |
<param name="Content-Type" location="header" static="application/json"/> |
|
990 |
</command> |
|
991 |
</commands> |
|
992 |
</client> |
|
993 |
``` |
|
994 |
|
|
995 |
**After** |
|
996 |
|
|
997 |
```json |
|
998 |
{ |
|
999 |
"name": "Zendesk REST API v2", |
|
1000 |
"apiVersion": "2012-12-31", |
|
1001 |
"description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users", |
|
1002 |
"operations": { |
|
1003 |
"list_groups": { |
|
1004 |
"httpMethod":"GET", |
|
1005 |
"uri": "groups.json", |
|
1006 |
"summary": "Get a list of groups" |
|
1007 |
}, |
|
1008 |
"search_groups":{ |
|
1009 |
"httpMethod":"GET", |
|
1010 |
"uri": "search.json?query=\"{query} type:group\"", |
|
1011 |
"summary": "Uses a search query to get a list of groups", |
|
1012 |
"parameters":{ |
|
1013 |
"query":{ |
|
1014 |
"location": "uri", |
|
1015 |
"description":"Zendesk Search Query", |
|
1016 |
"type": "string", |
|
1017 |
"required": true |
|
1018 |
} |
|
1019 |
} |
|
1020 |
}, |
|
1021 |
"create_group": { |
|
1022 |
"httpMethod":"POST", |
|
1023 |
"uri": "groups.json", |
|
1024 |
"summary": "Create a group", |
|
1025 |
"parameters":{ |
|
1026 |
"data": { |
|
1027 |
"type": "array", |
|
1028 |
"location": "body", |
|
1029 |
"description":"Group JSON", |
|
1030 |
"filters": "json_encode", |
|
1031 |
"required": true |
|
1032 |
}, |
|
1033 |
"Content-Type":{ |
|
1034 |
"type": "string", |
|
1035 |
"location":"header", |
|
1036 |
"static": "application/json" |
|
1037 |
} |
|
1038 |
} |
|
1039 |
}, |
|
1040 |
"delete_group": { |
|
1041 |
"httpMethod":"DELETE", |
|
1042 |
"uri": "groups/{id}.json", |
|
1043 |
"summary": "Delete a group", |
|
1044 |
"parameters":{ |
|
1045 |
"id":{ |
|
1046 |
"location": "uri", |
|
1047 |
"description":"Group to delete by ID", |
|
1048 |
"type": "integer", |
|
1049 |
"required": true |
|
1050 |
} |
|
1051 |
} |
|
1052 |
}, |
|
1053 |
"get_group": { |
|
1054 |
"httpMethod":"GET", |
|
1055 |
"uri": "groups/{id}.json", |
|
1056 |
"summary": "Get a ticket", |
|
1057 |
"parameters":{ |
|
1058 |
"id":{ |
|
1059 |
"location": "uri", |
|
1060 |
"description":"Group to get by ID", |
|
1061 |
"type": "integer", |
|
1062 |
"required": true |
|
1063 |
} |
|
1064 |
} |
|
1065 |
}, |
|
1066 |
"update_group": { |
|
1067 |
"httpMethod":"PUT", |
|
1068 |
"uri": "groups/{id}.json", |
|
1069 |
"summary": "Update a group", |
|
1070 |
"parameters":{ |
|
1071 |
"id": { |
|
1072 |
"location": "uri", |
|
1073 |
"description":"Group to update by ID", |
|
1074 |
"type": "integer", |
|
1075 |
"required": true |
|
1076 |
}, |
|
1077 |
"data": { |
|
1078 |
"type": "array", |
|
1079 |
"location": "body", |
|
1080 |
"description":"Group JSON", |
|
1081 |
"filters": "json_encode", |
|
1082 |
"required": true |
|
1083 |
}, |
|
1084 |
"Content-Type":{ |
|
1085 |
"type": "string", |
|
1086 |
"location":"header", |
|
1087 |
"static": "application/json" |
|
1088 |
} |
|
1089 |
} |
|
1090 |
} |
|
1091 |
} |
|
1092 |
``` |
|
1093 |
|
|
1094 |
### Guzzle\Service\Description\ServiceDescription |
|
1095 |
|
|
1096 |
Commands are now called Operations |
|
1097 |
|
|
1098 |
**Before** |
|
1099 |
|
|
1100 |
```php |
|
1101 |
use Guzzle\Service\Description\ServiceDescription; |
|
1102 |
|
|
1103 |
$sd = new ServiceDescription(); |
|
1104 |
$sd->getCommands(); // @returns ApiCommandInterface[] |
|
1105 |
$sd->hasCommand($name); |
|
1106 |
$sd->getCommand($name); // @returns ApiCommandInterface|null |
|
1107 |
$sd->addCommand($command); // @param ApiCommandInterface $command |
|
1108 |
``` |
|
1109 |
|
|
1110 |
**After** |
|
1111 |
|
|
1112 |
```php |
|
1113 |
use Guzzle\Service\Description\ServiceDescription; |
|
1114 |
|
|
1115 |
$sd = new ServiceDescription(); |
|
1116 |
$sd->getOperations(); // @returns OperationInterface[] |
|
1117 |
$sd->hasOperation($name); |
|
1118 |
$sd->getOperation($name); // @returns OperationInterface|null |
|
1119 |
$sd->addOperation($operation); // @param OperationInterface $operation |
|
1120 |
``` |
|
1121 |
|
|
1122 |
### Guzzle\Common\Inflection\Inflector |
|
1123 |
|
|
1124 |
Namespace is now `Guzzle\Inflection\Inflector` |
|
1125 |
|
|
1126 |
### Guzzle\Http\Plugin |
|
1127 |
|
|
1128 |
Namespace is now `Guzzle\Plugin`. Many other changes occur within this namespace and are detailed in their own sections below. |
|
1129 |
|
|
1130 |
### Guzzle\Http\Plugin\LogPlugin and Guzzle\Common\Log |
|
1131 |
|
|
1132 |
Now `Guzzle\Plugin\Log\LogPlugin` and `Guzzle\Log` respectively. |
|
1133 |
|
|
1134 |
**Before** |
|
1135 |
|
|
1136 |
```php |
|
1137 |
use Guzzle\Common\Log\ClosureLogAdapter; |
|
1138 |
use Guzzle\Http\Plugin\LogPlugin; |
|
1139 |
|
|
1140 |
/** @var \Guzzle\Http\Client */ |
|
1141 |
$client; |
|
1142 |
|
|
1143 |
// $verbosity is an integer indicating desired message verbosity level |
|
1144 |
$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE); |
|
1145 |
``` |
|
1146 |
|
|
1147 |
**After** |
|
1148 |
|
|
1149 |
```php |
|
1150 |
use Guzzle\Log\ClosureLogAdapter; |
|
1151 |
use Guzzle\Log\MessageFormatter; |
|
1152 |
use Guzzle\Plugin\Log\LogPlugin; |
|
1153 |
|
|
1154 |
/** @var \Guzzle\Http\Client */ |
|
1155 |
$client; |
|
1156 |
|
|
1157 |
// $format is a string indicating desired message format -- @see MessageFormatter |
|
1158 |
$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT); |
|
1159 |
``` |
|
1160 |
|
|
1161 |
### Guzzle\Http\Plugin\CurlAuthPlugin |
|
1162 |
|
|
1163 |
Now `Guzzle\Plugin\CurlAuth\CurlAuthPlugin`. |
|
1164 |
|
|
1165 |
### Guzzle\Http\Plugin\ExponentialBackoffPlugin |
|
1166 |
|
|
1167 |
Now `Guzzle\Plugin\Backoff\BackoffPlugin`, and other changes. |
|
1168 |
|
|
1169 |
**Before** |
|
1170 |
|
|
1171 |
```php |
|
1172 |
use Guzzle\Http\Plugin\ExponentialBackoffPlugin; |
|
1173 |
|
|
1174 |
$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge( |
|
1175 |
ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429) |
|
1176 |
)); |
|
1177 |
|
|
1178 |
$client->addSubscriber($backoffPlugin); |
|
1179 |
``` |
|
1180 |
|
|
1181 |
**After** |
|
1182 |
|
|
1183 |
```php |
|
1184 |
use Guzzle\Plugin\Backoff\BackoffPlugin; |
|
1185 |
use Guzzle\Plugin\Backoff\HttpBackoffStrategy; |
|
1186 |
|
|
1187 |
// Use convenient factory method instead -- see implementation for ideas of what |
|
1188 |
// you can do with chaining backoff strategies |
|
1189 |
$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge( |
|
1190 |
HttpBackoffStrategy::getDefaultFailureCodes(), array(429) |
|
1191 |
)); |
|
1192 |
$client->addSubscriber($backoffPlugin); |
|
1193 |
``` |
|
1194 |
|
|
1195 |
### Known Issues |
|
1196 |
|
|
1197 |
#### [BUG] Accept-Encoding header behavior changed unintentionally. |
|
1198 |
|
|
1199 |
(See #217) (Fixed in 09daeb8c666fb44499a0646d655a8ae36456575e) |
|
1200 |
|
|
1201 |
In version 2.8 setting the `Accept-Encoding` header would set the CURLOPT_ENCODING option, which permitted cURL to |
|
1202 |
properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen. |
|
1203 |
See issue #217 for a workaround, or use a version containing the fix. |