Guzzle now uses PSR-7 for HTTP messages.
Due to the fact that these messages are immutable, this prompted a refactoring
of Guzzle to use a middleware based system rather than an event system. Any
HTTP message interaction (e.g., GuzzleHttp\Message\Request
) need to be
updated to work with the new immutable PSR-7 request and response objects. Any
event listeners or subscribers need to be updated to become middleware
functions that wrap handlers (or are injected into a
GuzzleHttp\HandlerStack
).
GuzzleHttp\BatchResults
GuzzleHttp\Collection
GuzzleHttp\HasDataTrait
GuzzleHttp\ToArrayInterface
guzzlehttp/streams
dependency has been removed. Stream functionality
is now present in the GuzzleHttp\Psr7
namespace provided by the
guzzlehttp/psr7
package.guzzlehttp/promises
library. We use a custom promise library for three
significant reasons:
GuzzleHttp\Mimetypes
has been moved to a function in
GuzzleHttp\Psr7\mimetype_from_extension
and
GuzzleHttp\Psr7\mimetype_from_filename
.GuzzleHttp\Query
and GuzzleHttp\QueryParser
have been removed. Query
strings must now be passed into request objects as strings, or provided to
the query
request option when creating requests with clients. The query
option uses PHP's http_build_query
to convert an array to a string. If you
need a different serialization technique, you will need to pass the query
string in as a string. There are a couple helper functions that will make
working with query strings easier: GuzzleHttp\Psr7\parse_query
and
GuzzleHttp\Psr7\build_query
.GuzzleHttp\Handler
namespace. This significantly reduces
complexity in Guzzle, removes a dependency, and improves performance. RingPHP
will be maintained for Guzzle 5 support, but will no longer be a part of
Guzzle 6.Event
namespace.Subscriber
namespace.Transaction
classRequestFsm
RingBridge
GuzzleHttp\Subscriber\Cookie
is now provided by
GuzzleHttp\Middleware::cookies
GuzzleHttp\Subscriber\HttpError
is now provided by
GuzzleHttp\Middleware::httpError
GuzzleHttp\Subscriber\History
is now provided by
GuzzleHttp\Middleware::history
GuzzleHttp\Subscriber\Mock
is now provided by
GuzzleHttp\Handler\MockHandler
GuzzleHttp\Subscriber\Prepare
is now provided by
GuzzleHttp\PrepareBodyMiddleware
GuzzleHttp\Subscriber\Redirect
is now provided by
GuzzleHttp\RedirectMiddleware
Psr\Http\Message\UriInterface
(implements in
GuzzleHttp\Psr7\Uri
) for URI support. GuzzleHttp\Url
is now gone.GuzzleHttp\Utils
have been moved to namespaced
functions under the GuzzleHttp
namespace. This requires either a Composer
based autoloader or you to include functions.php.GuzzleHttp\ClientInterface::getDefaultOption
has been renamed to
GuzzleHttp\ClientInterface::getConfig
.GuzzleHttp\ClientInterface::setDefaultOption
has been removed.json
and xml
methods of response objects has been removed. With the
migration to strictly adhering to PSR-7 as the interface for Guzzle messages,
adding methods to message interfaces would actually require Guzzle messages
to extend from PSR-7 messages rather then work with them directly.The change to PSR-7 unfortunately required significant refactoring to Guzzle due to the fact that PSR-7 messages are immutable. Guzzle 5 relied on an event system from plugins. The event system relied on mutability of HTTP messages and side effects in order to work. With immutable messages, you have to change your workflow to become more about either returning a value (e.g., functional middlewares) or setting a value on an object. Guzzle v6 has chosen the functional middleware approach.
Instead of using the event system to listen for things like the before
event,
you now create a stack based middleware function that intercepts a request on
the way in and the promise of the response on the way out. This is a much
simpler and more predictable approach than the event system and works nicely
with PSR-7 middleware. Due to the use of promises, the middleware system is
also asynchronous.
v5:
use GuzzleHttp\Event\BeforeEvent;
$client = new GuzzleHttp\Client();
// Get the emitter and listen to the before event.
$client->getEmitter()->on('before', function (BeforeEvent $e) {
// Guzzle v5 events relied on mutation
$e->getRequest()->setHeader('X-Foo', 'Bar');
});
v6:
In v6, you can modify the request before it is sent using the mapRequest
middleware. The idiomatic way in v6 to modify the request/response lifecycle is
to setup a handler middleware stack up front and inject the handler into a
client.
use GuzzleHttp\Middleware;
// Create a handler stack that has all of the default middlewares attached
$handler = GuzzleHttp\HandlerStack::create();
// Push the handler onto the handler stack
$handler->push(Middleware::mapRequest(function (RequestInterface $request) {
// Notice that we have to return a request object
return $request->withHeader('X-Foo', 'Bar');
}));
// Inject the handler into the client
$client = new GuzzleHttp\Client(['handler' => $handler]);
This version added the form_params
and multipart
request options. form_params
is an associative array of
strings or array of strings and is used to serialize an
application/x-www-form-urlencoded
POST request. The
multipart
option is now used to send a multipart/form-data POST request.
GuzzleHttp\Post\PostFile
has been removed. Use the multipart
option to add
POST files to a multipart/form-data request.
The body
option no longer accepts an array to send POST requests. Please use
multipart
or form_params
instead.
The base_url
option has been renamed to base_uri
.
Guzzle now uses RingPHP to send
HTTP requests. The adapter
option in a GuzzleHttp\Client
constructor
is still supported, but it has now been renamed to handler
. Instead of
passing a GuzzleHttp\Adapter\AdapterInterface
, you must now pass a PHP
callable
that follows the RingPHP specification.
Fluent interfaces were removed from the following classes:
GuzzleHttp\Collection
GuzzleHttp\Url
GuzzleHttp\Query
GuzzleHttp\Post\PostBody
GuzzleHttp\Cookie\SetCookie
Removed "functions.php", so that Guzzle is truly PSR-4 compliant. The following functions can be used as replacements.
GuzzleHttp\json_decode
-> GuzzleHttp\Utils::jsonDecode
GuzzleHttp\get_path
-> GuzzleHttp\Utils::getPath
GuzzleHttp\Utils::setPath
-> GuzzleHttp\set_path
GuzzleHttp\Pool::batch
-> GuzzleHttp\batch
. This function is, however,
deprecated in favor of using GuzzleHttp\Pool::batch()
.The "procedural" global client has been removed with no replacement (e.g.,
GuzzleHttp\get()
, GuzzleHttp\post()
, etc.). Use a GuzzleHttp\Client
object as a replacement.
The concept of "throwImmediately" has been removed from exceptions and error events. This control mechanism was used to stop a transfer of concurrent requests from completing. This can now be handled by throwing the exception or by cancelling a pool of requests or each outstanding future request individually.
Removed the "headers" event. This event was only useful for changing the body a response once the headers of the response were known. You can implement a similar behavior in a number of ways. One example might be to use a FnStream that has access to the transaction being sent. For example, when the first byte is written, you could check if the response headers match your expectations, and if so, change the actual stream body that is being written to.
Removed the asArray
parameter from
GuzzleHttp\Message\MessageInterface::getHeader
. If you want to get a header
value as an array, then use the newly added getHeaderAsArray()
method of
MessageInterface
. This change makes the Guzzle interfaces compatible with
the PSR-7 interfaces.
GuzzleHttp\Event\EmitterInterface
(resulting in significant
speed and functionality improvements).Changes per Guzzle 3.x namespace are described below.
The Guzzle\Batch
namespace has been removed. This is best left to
third-parties to implement on top of Guzzle's core HTTP library.
The Guzzle\Cache
namespace has been removed. (Todo: No suitable replacement
has been implemented yet, but hoping to utilize a PSR cache interface).
FromConfigInterface
has been removed.Guzzle\Common\Version
has been removed. The VERSION constant can be found
at GuzzleHttp\ClientInterface::VERSION
.getAll
has been removed. Use toArray
to convert a collection to an array.inject
has been removed.keySearch
has been removed.getPath
no longer supports wildcard expressions. Use something better like
JMESPath for this.setPath
now supports appending to an existing array via the []
notation.Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now uses
GuzzleHttp\Event\Emitter
.
Symfony\Component\EventDispatcher\EventDispatcherInterface
is replaced by
GuzzleHttp\Event\EmitterInterface
.Symfony\Component\EventDispatcher\EventDispatcher
is replaced by
GuzzleHttp\Event\Emitter
.Symfony\Component\EventDispatcher\Event
is replaced by
GuzzleHttp\Event\Event
, and Guzzle now has an EventInterface in
GuzzleHttp\Event\EventInterface
.AbstractHasDispatcher
has moved to a trait, HasEmitterTrait
, and
HasDispatcherInterface
has moved to HasEmitterInterface
. Retrieving the
event emitter of a request, client, etc. now uses the getEmitter
method
rather than the getDispatcher
method.once()
method to add a listener that automatically removes itself
the first time it is invoked.listeners()
method to retrieve a list of event listeners rather than
the getListeners()
method.emit()
instead of dispatch()
to emit an event from an emitter.attach()
instead of addSubscriber()
and detach()
instead of
removeSubscriber()
.$mock = new Mock();
// 3.x
$request->getEventDispatcher()->addSubscriber($mock);
$request->getEventDispatcher()->removeSubscriber($mock);
// 4.x
$request->getEmitter()->attach($mock);
$request->getEmitter()->detach($mock);
Use the on()
method to add a listener rather than the addListener()
method.
// 3.x
$request->getEventDispatcher()->addListener('foo', function (Event $event) { /* ... */ } );
// 4.x
$request->getEmitter()->on('foo', function (Event $event, $name) { /* ... */ } );
src/cacert.pem
.complete
and error
events to asynchronously manage parallel request transfers.Guzzle\Http\Url
has moved to GuzzleHttp\Url
.Guzzle\Http\QueryString
has moved to GuzzleHttp\Query
.GuzzleHttp\StaticClient
has been removed. Use the functions provided in
functions.php
for an easy to use static client instance.GuzzleHttp\Exception
have been updated to all extend from
GuzzleHttp\Exception\TransferException
.Calling methods like get()
, post()
, head()
, etc. no longer create and
return a request, but rather creates a request, sends the request, and returns
the response.
// 3.0
$request = $client->get('/');
$response = $request->send();
// 4.0
$response = $client->get('/');
// or, to mirror the previous behavior
$request = $client->createRequest('GET', '/');
$response = $client->send($request);
GuzzleHttp\ClientInterface
has changed.
send
method no longer accepts more than one request. Use sendAll
to
send multiple requests in parallel.setUserAgent()
has been removed. Use a default request option instead. You
could, for example, do something like:
$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())
.setSslVerification()
has been removed. Use default request options instead,
like $client->setConfig('defaults/verify', true)
.GuzzleHttp\Client
has changed.
base_url
string or array to use a URI template as the base URL of a client.
You can also specify a defaults
key that is an associative array of default
request options. You can pass an adapter
to use a custom adapter,
batch_adapter
to use a custom adapter for sending requests in parallel, or
a message_factory
to change the factory used to create HTTP requests and
responses.client.create_request
event.createRequest
, get
, put
, etc.) in order to expand a URI template.Messages no longer have references to their counterparts (i.e., a request no
longer has a reference to it's response, and a response no loger has a
reference to its request). This association is now managed through a
GuzzleHttp\Adapter\TransactionInterface
object. You can get references to
these transaction objects using request events that are emitted over the
lifecycle of a request.
GuzzleHttp\Message\EntityEnclosingRequest
and
GuzzleHttp\Message\EntityEnclosingRequestInterface
have been removed. The
separation between requests that contain a body and requests that do not
contain a body has been removed, and now GuzzleHttp\Message\RequestInterface
handles both use cases.GuzzleHttp\Response
object now accept a
GuzzleHttp\Message\ResponseInterface
.GuzzleHttp\Message\RequestFactoryInterface
has been renamed to
GuzzleHttp\Message\MessageFactoryInterface
. This interface is used to create
both requests and responses and is implemented in
GuzzleHttp\Message\MessageFactory
.GuzzleHttp\Post\PostBodyInterface
to control the format of a POST body. Requests that are created using a
standard GuzzleHttp\Message\MessageFactoryInterface
will automatically use
a GuzzleHttp\Post\PostBody
body if the body was passed as an array or if
the method is POST and no body is provided.$request = $client->createRequest('POST', '/');
$request->getBody()->setField('foo', 'bar');
$request->getBody()->addFile(new PostFile('file_key', fopen('/path/to/content', 'r')));
GuzzleHttp\Message\Header
has been removed. Header values are now simply
represented by an array of values or as a string. Header values are returned
as a string by default when retrieving a header value from a message. You can
pass an optional argument of true
to retrieve a header value as an array
of strings instead of a single concatenated string.GuzzleHttp\PostFile
and GuzzleHttp\PostFileInterface
have been moved to
GuzzleHttp\Post
. This interface has been simplified and now allows the
addition of arbitrary headers.GuzzleHttp\Message\Header\Link
have been removed. Most
of the custom headers are now handled separately in specific
subscribers/plugins, and GuzzleHttp\Message\HeaderValues::parseParams()
has
been updated to properly handle headers that contain parameters (like the
Link
header).GuzzleHttp\Message\Response::getInfo()
and
GuzzleHttp\Message\Response::setInfo()
have been removed. Use the event
system to retrieve this type of information.GuzzleHttp\Message\Response::getRawHeaders()
has been removed.GuzzleHttp\Message\Response::getMessage()
has been removed.GuzzleHttp\Message\Response::calculateAge()
and other cache specific
methods have moved to the CacheSubscriber.getContentMd5()
have been removed.
Just use getHeader('Content-MD5')
instead.GuzzleHttp\Message\Response::setRequest()
and
GuzzleHttp\Message\Response::getRequest()
have been removed. Use the event
system to work with request and response objects as a transaction.GuzzleHttp\Message\Response::getRedirectCount()
has been removed. Use the
Redirect subscriber instead.GuzzleHttp\Message\Response::isSuccessful()
and other related methods have
been removed. Use getStatusCode()
instead.Streaming requests can now be created by a client directly, returning a
GuzzleHttp\Message\ResponseInterface
object that contains a body stream
referencing an open PHP HTTP stream.
// 3.0
use Guzzle\Stream\PhpStreamRequestFactory;
$request = $client->get('/');
$factory = new PhpStreamRequestFactory();
$stream = $factory->fromRequest($request);
$data = $stream->read(1024);
// 4.0
$response = $client->get('/', ['stream' => true]);
// Read some data off of the stream in the response body
$data = $response->getBody()->read(1024);
The configureRedirects()
method has been removed in favor of a
allow_redirects
request option.
// Standard redirects with a default of a max of 5 redirects
$request = $client->createRequest('GET', '/', ['allow_redirects' => true]);
// Strict redirects with a custom number of redirects
$request = $client->createRequest('GET', '/', [
'allow_redirects' => ['max' => 5, 'strict' => true]
]);
EntityBody interfaces and classes have been removed or moved to
GuzzleHttp\Stream
. All classes and interfaces that once required
GuzzleHttp\EntityBodyInterface
now require
GuzzleHttp\Stream\StreamInterface
. Creating a new body for a request no
longer uses GuzzleHttp\EntityBody::factory
but now uses
GuzzleHttp\Stream\Stream::factory
or even better:
GuzzleHttp\Stream\create()
.
Guzzle\Http\EntityBodyInterface
is now GuzzleHttp\Stream\StreamInterface
Guzzle\Http\EntityBody
is now GuzzleHttp\Stream\Stream
Guzzle\Http\CachingEntityBody
is now GuzzleHttp\Stream\CachingStream
Guzzle\Http\ReadLimitEntityBody
is now GuzzleHttp\Stream\LimitStream
Guzzle\Http\IoEmittyinEntityBody
has been removed.Requests previously submitted a large number of requests. The number of events
emitted over the lifecycle of a request has been significantly reduced to make
it easier to understand how to extend the behavior of a request. All events
emitted during the lifecycle of a request now emit a custom
GuzzleHttp\Event\EventInterface
object that contains context providing
methods and a way in which to modify the transaction at that specific point in
time (e.g., intercept the request and set a response on the transaction).
request.before_send
has been renamed to before
and now emits a
GuzzleHttp\Event\BeforeEvent
request.complete
has been renamed to complete
and now emits a
GuzzleHttp\Event\CompleteEvent
.request.sent
has been removed. Use complete
.request.success
has been removed. Use complete
.error
is now an event that emits a GuzzleHttp\Event\ErrorEvent
.request.exception
has been removed. Use error
.request.receive.status_line
has been removed.curl.callback.progress
has been removed. Use a custom StreamInterface
to
maintain a status update.curl.callback.write
has been removed. Use a custom StreamInterface
to
intercept writes.curl.callback.read
has been removed. Use a custom StreamInterface
to
intercept reads.headers
is a new event that is emitted after the response headers of a
request have been received before the body of the response is downloaded. This
event emits a GuzzleHttp\Event\HeadersEvent
.
You can intercept a request and inject a response using the intercept()
event
of a GuzzleHttp\Event\BeforeEvent
, GuzzleHttp\Event\CompleteEvent
, and
GuzzleHttp\Event\ErrorEvent
event.
See: http://docs.guzzlephp.org/en/latest/events.html
The Guzzle\Inflection
namespace has been removed. This is not a core concern
of Guzzle.
The Guzzle\Iterator
namespace has been removed.
Guzzle\Iterator\AppendIterator
, Guzzle\Iterator\ChunkedIterator
, and
Guzzle\Iterator\MethodProxyIterator
are nice, but not a core requirement of
Guzzle itself.Guzzle\Iterator\FilterIterator
is no longer needed because an equivalent
class is shipped with PHP 5.4.Guzzle\Iterator\MapIterator
is not really needed when using PHP 5.5 because
it's easier to just wrap an iterator in a generator that maps values.For a replacement of these iterators, see https://github.com/nikic/iter
The LogPlugin has moved to https://github.com/guzzle/log-subscriber. The
Guzzle\Log
namespace has been removed. Guzzle now relies on
Psr\Log\LoggerInterface
for all logging. The MessageFormatter class has been
moved to GuzzleHttp\Subscriber\Log\Formatter
.
The Guzzle\Parser
namespace has been removed. This was previously used to
make it possible to plug in custom parsers for cookies, messages, URI
templates, and URLs; however, this level of complexity is not needed in Guzzle
so it has been removed.
GuzzleHttp\Cookie\SetCookie::fromString
.GuzzleHttp\Message\MessageFactory::fromMessage
. Message parsing is only
used in debugging or deserializing messages, so it doesn't make sense for
Guzzle as a library to add this level of complexity to parsing messages.GuzzleHttp\UriTemplate
. The Guzzle library will automatically use the PECL
URI template library if it is installed.GuzzleHttp\Url::fromString
(previously
it was Guzzle\Http\Url::factory()
). If custom URL parsing is necessary,
then developers are free to subclass GuzzleHttp\Url
.The Guzzle\Plugin
namespace has been renamed to GuzzleHttp\Subscriber
.
Several plugins are shipping with the core Guzzle library under this namespace.
GuzzleHttp\Subscriber\Cookie
: Replaces the old CookiePlugin. Cookie jar
code has moved to GuzzleHttp\Cookie
.GuzzleHttp\Subscriber\History
: Replaces the old HistoryPlugin.GuzzleHttp\Subscriber\HttpError
: Throws errors when a bad HTTP response is
received.GuzzleHttp\Subscriber\Mock
: Replaces the old MockPlugin.GuzzleHttp\Subscriber\Prepare
: Prepares the body of a request just before
sending. This subscriber is attached to all requests by default.GuzzleHttp\Subscriber\Redirect
: Replaces the RedirectPlugin.The following plugins have been removed (third-parties are free to re-implement these if needed):
GuzzleHttp\Plugin\Async
has been removed.GuzzleHttp\Plugin\CurlAuth
has been removed.GuzzleHttp\Plugin\ErrorResponse\ErrorResponsePlugin
has been removed. This
functionality should instead be implemented with event listeners that occur
after normal response parsing occurs in the guzzle/command package.The following plugins are not part of the core Guzzle package, but are provided in separate repositories:
Guzzle\Http\Plugin\BackoffPlugin
has been rewritten to be much simpler
to build custom retry policies using simple functions rather than various
chained classes. See: https://github.com/guzzle/retry-subscriberGuzzle\Http\Plugin\Cache\CachePlugin
has moved to
https://github.com/guzzle/cache-subscriberGuzzle\Http\Plugin\Log\LogPlugin
has moved to
https://github.com/guzzle/log-subscriberGuzzle\Http\Plugin\Md5\Md5Plugin
has moved to
https://github.com/guzzle/message-integrity-subscriberGuzzle\Http\Plugin\Mock\MockPlugin
has moved to
GuzzleHttp\Subscriber\MockSubscriber
.Guzzle\Http\Plugin\Oauth\OauthPlugin
has moved to
https://github.com/guzzle/oauth-subscriberThe service description layer of Guzzle has moved into two separate packages:
Stream have moved to a separate package available at https://github.com/guzzle/streams.
Guzzle\Stream\StreamInterface
has been given a large update to cleanly take
on the responsibilities of Guzzle\Http\EntityBody
and
Guzzle\Http\EntityBodyInterface
now that they have been removed. The number
of methods implemented by the StreamInterface
has been drastically reduced to
allow developers to more easily extend and decorate stream behavior.
getStream
and setStream
have been removed to better encapsulate streams.getMetadata
and setMetadata
have been removed in favor of
GuzzleHttp\Stream\MetadataStreamInterface
.getWrapper
, getWrapperData
, getStreamType
, and getUri
have all been
removed. This data is accessible when
using streams that implement GuzzleHttp\Stream\MetadataStreamInterface
.rewind
has been removed. Use seek(0)
for a similar behavior.detachStream
has been renamed to detach
.feof
has been renamed to eof
.ftell
has been renamed to tell
.readLine
has moved from an instance method to a static class method of
GuzzleHttp\Stream\Stream
.GuzzleHttp\Stream\MetadataStreamInterface
has been added to denote streams
that contain additional metadata accessible via getMetadata()
.
GuzzleHttp\Stream\StreamInterface::getMetadata
and
GuzzleHttp\Stream\StreamInterface::setMetadata
have been removed.
The entire concept of the StreamRequestFactory has been removed. The way this
was used in Guzzle 3 broke the actual interface of sending streaming requests
(instead of getting back a Response, you got a StreamInterface). Streaming
PHP requests are now implemented through the GuzzleHttp\Adapter\StreamAdapter
.
\Guzzle\Common\Version::$emitWarnings = true;
The following APIs and options have been marked as deprecated:
Guzzle\Http\Message\Request::isResponseBodyRepeatable()
as deprecated. Use $request->getResponseBody()->isRepeatable()
instead.Guzzle\Http\Message\Request::canCache()
as deprecated. Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()
instead.Guzzle\Http\Message\Request::canCache()
as deprecated. Use Guzzle\Plugin\Cache\DefaultCanCacheStrategy->canCacheRequest()
instead.Guzzle\Http\Message\Request::setIsRedirect()
as deprecated. Use the HistoryPlugin instead.Guzzle\Http\Message\Request::isRedirect()
as deprecated. Use the HistoryPlugin instead.Guzzle\Cache\CacheAdapterFactory::factory()
as deprecatedGuzzle\Service\Client::enableMagicMethods()
as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.Guzzle\Parser\Url\UrlParser
as deprecated. Just use PHP's parse_url()
and percent encode your UTF-8.Guzzle\Common\Collection::inject()
as deprecated.Guzzle\Plugin\CurlAuth\CurlAuthPlugin
as deprecated. Use
$client->getConfig()->setPath('request.options/auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));
or
$client->setDefaultOption('auth', array('user', 'pass', 'Basic|Digest|NTLM|Any'));
3.7 introduces request.options
as a parameter for a client configuration and as an optional argument to all creational
request methods. When paired with a client's configuration settings, these options allow you to specify default settings
for various aspects of a request. Because these options make other previous configuration options redundant, several
configuration options and methods of a client and AbstractCommand have been deprecated.
Guzzle\Service\Client::getDefaultHeaders()
as deprecated. Use $client->getDefaultOption('headers')
.Guzzle\Service\Client::setDefaultHeaders()
as deprecated. Use $client->setDefaultOption('headers/{header_name}', 'value')
.Guzzle\Http\Client
as deprecated. Use $client->setDefaultOption('params/{param_name}', 'value')
Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand. These will work through Guzzle 4.0
$command = $client->getCommand('foo', array(
'command.headers' => array('Test' => '123'),
'command.response_body' => '/path/to/file'
));
// Should be changed to:
$command = $client->getCommand('foo', array(
'command.request_options' => array(
'headers' => array('Test' => '123'),
'save_as' => '/path/to/file'
)
));
Additions and changes (you will need to update any implementations or subclasses you may have created):
$options
argument to the end of the following methods of Guzzle\Http\ClientInterface
:
createRequest, head, delete, put, patch, post, options, prepareRequest$options
argument to the end of Guzzle\Http\Message\Request\RequestFactoryInterface::createRequest()
applyOptions()
method to Guzzle\Http\Message\Request\RequestFactoryInterface
Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $body = null)
to
Guzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())
. You can still pass in a
resource, string, or EntityBody into the $options parameter to specify the download location of the response.Guzzle\Common\Collection::__construct($data)
to no longer accepts a null value for $data
but a
default array()
Guzzle\Stream\StreamInterface::isRepeatable
Guzzle\Http\Client::expandTemplate
and getUriTemplate
protected methods.The following methods were removed from interfaces. All of these methods are still available in the concrete classes that implement them, but you should update your code to use alternative methods:
Guzzle\Http\ClientInterface::setDefaultHeaders(). Use
$client->getConfig()->setPath('request.options/headers/{header_name}', 'value'). or
$client->getConfig()->setPath('request.options/headers', array('header_name' => 'value'))or
$client->setDefaultOption('headers/{header_name}', 'value'). or
$client->setDefaultOption('headers', array('header_name' => 'value'))`.Guzzle\Http\ClientInterface::getDefaultHeaders(). Use
$client->getConfig()->getPath('request.options/headers')`.Guzzle\Http\ClientInterface::expandTemplate()
. This is an implementation detail.Guzzle\Http\ClientInterface::setRequestFactory()
. This is an implementation detail.Guzzle\Http\ClientInterface::getCurlMulti()
. This is a very specific implementation detail.Guzzle\Http\Message\RequestInterface::canCache
. Use the CachePlugin.Guzzle\Http\Message\RequestInterface::setIsRedirect
. Use the HistoryPlugin.Guzzle\Http\Message\RequestInterface::isRedirect
. Use the HistoryPlugin.CacheStorageInterface::cache($key, Response $response, $ttl = null)
has changed to cache(RequestInterface
$request, Response $response);
CacheStorageInterface::fetch($key)
has changed to fetch(RequestInterface $request);
CacheStorageInterface::delete($key)
has changed to delete(RequestInterface $request);
CacheStorageInterface::purge($url)
DefaultRevalidation::__construct(CacheKeyProviderInterface $cacheKey, CacheStorageInterface $cache, CachePlugin
$plugin)
has changed to DefaultRevalidation::__construct(CacheStorageInterface $cache,
CanCacheStrategyInterface $canCache = null)
RevalidationInterface::shouldRevalidate(RequestInterface $request, Response $response)
If you previously relied on Guzzle\Http\Message\Header::raw(), then you will need to update your code to use the HeaderInterface (e.g. toArray(), getAll(), etc.).
Guzzle\Service\Command\CommandInterface
typehint now request a
Guzzle\Service\Command\ArrayCommandInterface
.Guzzle\Http\Message\RequestInterface::startResponse()
to the RequestInterface to handle injecting a response
on a request while the request is still being transferredGuzzle\Service\Command\CommandInterface
now extends from ToArrayInterface and ArrayAccessBase URLs of a client now follow the rules of http://tools.ietf.org/html/rfc3986#section-5.2.2 when merging URLs.
Guzzle\Http\Message\Response::getEtag()
no longer strips quotes around the ETag response header
The Guzzle\Http\Utils
class was removed. This class was only used for testing.
Guzzle\Stream\Stream::getWrapper()
and Guzzle\Stream\Stream::getStreamType()
are no longer converted to lowercase.
Emitting IO events from a RequestMediator is now a parameter that must be set in a request's curl options using the 'emit_io' key. This was previously set under a request's parameters using 'curl.emit_io'
Before 3.2, the same CurlMulti object was reused globally for each client. This can cause issue where plugins added to a single client can pollute requests dispatched from other clients.
If you still wish to reuse the same CurlMulti object with each client, then you can add a listener to the
ServiceBuilder's service_builder.create_client
event to inject a custom CurlMulti object into each client as it is
created.
$multi = new Guzzle\Http\Curl\CurlMulti();
$builder = Guzzle\Service\Builder\ServiceBuilder::factory('/path/to/config.json');
$builder->addListener('service_builder.create_client', function ($event) use ($multi) {
$event['client']->setCurlMulti($multi);
}
});
URLs no longer have a default path value of '/' if no path was specified.
Before:
$request = $client->get('http://www.foo.com');
echo $request->getUrl();
// >> http://www.foo.com/
After:
$request = $client->get('http://www.foo.com');
echo $request->getUrl();
// >> http://www.foo.com
The exception message for Guzzle\Http\Exception\BadResponseException
no longer contains the full HTTP request and
response information. You can, however, get access to the request and response object by calling getRequest()
or
getResponse()
on the exception object.
Multi-valued query parameters are no longer aggregated using a callback function. Guzzle\Http\Query
now has a
setAggregator() method that accepts a Guzzle\Http\QueryAggregator\QueryAggregatorInterface
object. This object is
responsible for handling the aggregation of multi-valued query string variables into a flattened hash.
Change \Guzzle\Service\Inspector::fromConfig
to \Guzzle\Common\Collection::fromConfig
Before
use Guzzle\Service\Inspector;
class YourClient extends \Guzzle\Service\Client
{
public static function factory($config = array())
{
$default = array();
$required = array('base_url', 'username', 'api_key');
$config = Inspector::fromConfig($config, $default, $required);
$client = new self(
$config->get('base_url'),
$config->get('username'),
$config->get('api_key')
);
$client->setConfig($config);
$client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
return $client;
}
After
use Guzzle\Common\Collection;
class YourClient extends \Guzzle\Service\Client
{
public static function factory($config = array())
{
$default = array();
$required = array('base_url', 'username', 'api_key');
$config = Collection::fromConfig($config, $default, $required);
$client = new self(
$config->get('base_url'),
$config->get('username'),
$config->get('api_key')
);
$client->setConfig($config);
$client->setDescription(ServiceDescription::factory(__DIR__ . DIRECTORY_SEPARATOR . 'client.json'));
return $client;
}
Before
<?xml version="1.0" encoding="UTF-8"?>
<client>
<commands>
<!-- Groups -->
<command name="list_groups" method="GET" uri="groups.json">
<doc>Get a list of groups</doc>
</command>
<command name="search_groups" method="GET" uri='search.json?query="{{query}} type:group"'>
<doc>Uses a search query to get a list of groups</doc>
<param name="query" type="string" required="true" />
</command>
<command name="create_group" method="POST" uri="groups.json">
<doc>Create a group</doc>
<param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
<param name="Content-Type" location="header" static="application/json"/>
</command>
<command name="delete_group" method="DELETE" uri="groups/{{id}}.json">
<doc>Delete a group by ID</doc>
<param name="id" type="integer" required="true"/>
</command>
<command name="get_group" method="GET" uri="groups/{{id}}.json">
<param name="id" type="integer" required="true"/>
</command>
<command name="update_group" method="PUT" uri="groups/{{id}}.json">
<doc>Update a group</doc>
<param name="id" type="integer" required="true"/>
<param name="data" type="array" location="body" filters="json_encode" doc="Group JSON"/>
<param name="Content-Type" location="header" static="application/json"/>
</command>
</commands>
</client>
After
{
"name": "Zendesk REST API v2",
"apiVersion": "2012-12-31",
"description":"Provides access to Zendesk views, groups, tickets, ticket fields, and users",
"operations": {
"list_groups": {
"httpMethod":"GET",
"uri": "groups.json",
"summary": "Get a list of groups"
},
"search_groups":{
"httpMethod":"GET",
"uri": "search.json?query=\"{query} type:group\"",
"summary": "Uses a search query to get a list of groups",
"parameters":{
"query":{
"location": "uri",
"description":"Zendesk Search Query",
"type": "string",
"required": true
}
}
},
"create_group": {
"httpMethod":"POST",
"uri": "groups.json",
"summary": "Create a group",
"parameters":{
"data": {
"type": "array",
"location": "body",
"description":"Group JSON",
"filters": "json_encode",
"required": true
},
"Content-Type":{
"type": "string",
"location":"header",
"static": "application/json"
}
}
},
"delete_group": {
"httpMethod":"DELETE",
"uri": "groups/{id}.json",
"summary": "Delete a group",
"parameters":{
"id":{
"location": "uri",
"description":"Group to delete by ID",
"type": "integer",
"required": true
}
}
},
"get_group": {
"httpMethod":"GET",
"uri": "groups/{id}.json",
"summary": "Get a ticket",
"parameters":{
"id":{
"location": "uri",
"description":"Group to get by ID",
"type": "integer",
"required": true
}
}
},
"update_group": {
"httpMethod":"PUT",
"uri": "groups/{id}.json",
"summary": "Update a group",
"parameters":{
"id": {
"location": "uri",
"description":"Group to update by ID",
"type": "integer",
"required": true
},
"data": {
"type": "array",
"location": "body",
"description":"Group JSON",
"filters": "json_encode",
"required": true
},
"Content-Type":{
"type": "string",
"location":"header",
"static": "application/json"
}
}
}
}
Commands are now called Operations
Before
use Guzzle\Service\Description\ServiceDescription;
$sd = new ServiceDescription();
$sd->getCommands(); // @returns ApiCommandInterface[]
$sd->hasCommand($name);
$sd->getCommand($name); // @returns ApiCommandInterface|null
$sd->addCommand($command); // @param ApiCommandInterface $command
After
use Guzzle\Service\Description\ServiceDescription;
$sd = new ServiceDescription();
$sd->getOperations(); // @returns OperationInterface[]
$sd->hasOperation($name);
$sd->getOperation($name); // @returns OperationInterface|null
$sd->addOperation($operation); // @param OperationInterface $operation
Namespace is now Guzzle\Inflection\Inflector
Namespace is now Guzzle\Plugin
. Many other changes occur within this namespace and are detailed in their own sections below.
Now Guzzle\Plugin\Log\LogPlugin
and Guzzle\Log
respectively.
Before
use Guzzle\Common\Log\ClosureLogAdapter;
use Guzzle\Http\Plugin\LogPlugin;
/** @var \Guzzle\Http\Client */
$client;
// $verbosity is an integer indicating desired message verbosity level
$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $verbosity = LogPlugin::LOG_VERBOSE);
After
use Guzzle\Log\ClosureLogAdapter;
use Guzzle\Log\MessageFormatter;
use Guzzle\Plugin\Log\LogPlugin;
/** @var \Guzzle\Http\Client */
$client;
// $format is a string indicating desired message format -- @see MessageFormatter
$client->addSubscriber(new LogPlugin(new ClosureLogAdapter(function($m) { echo $m; }, $format = MessageFormatter::DEBUG_FORMAT);
Now Guzzle\Plugin\CurlAuth\CurlAuthPlugin
.
Now Guzzle\Plugin\Backoff\BackoffPlugin
, and other changes.
Before
use Guzzle\Http\Plugin\ExponentialBackoffPlugin;
$backoffPlugin = new ExponentialBackoffPlugin($maxRetries, array_merge(
ExponentialBackoffPlugin::getDefaultFailureCodes(), array(429)
));
$client->addSubscriber($backoffPlugin);
After
use Guzzle\Plugin\Backoff\BackoffPlugin;
use Guzzle\Plugin\Backoff\HttpBackoffStrategy;
// Use convenient factory method instead -- see implementation for ideas of what
// you can do with chaining backoff strategies
$backoffPlugin = BackoffPlugin::getExponentialBackoff($maxRetries, array_merge(
HttpBackoffStrategy::getDefaultFailureCodes(), array(429)
));
$client->addSubscriber($backoffPlugin);
(See #217) (Fixed in 09daeb8c66
)
In version 2.8 setting the Accept-Encoding
header would set the CURLOPT_ENCODING option, which permitted cURL to
properly handle gzip/deflate compressed responses from the server. In versions affected by this bug this does not happen.
See issue #217 for a workaround, or use a version containing the fix.