Browse code

added appinfo/info.xml appinfo/signature.json CHANGELOG.txt lib/AppInfo/Application.php css/style.css providers/Plivo

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

removed appinfo/info.xml appinfo/signature.json CHANGELOG.txt lib/AppInfo/Application.php css/style.css providers/Plivo

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

Added README.md appinfo/info.xml appinfo/signature.json lib/Controller/AuthorApiController.php and the providers directory

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