| 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. |
| 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. |
| 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. |