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 aGuzzleHttp\HandlerStack
).
GuzzleHttp\BatchResults
GuzzleHttp\Collection
GuzzleHttp\HasDataTrait
GuzzleHttp\ToArrayInterface
guzzlehttp/streams
dependency has been removed. Stream functionalityGuzzleHttp\Psr7
namespace provided by theguzzlehttp/psr7
package.guzzlehttp/promises
library. We use a custom promise library for threeGuzzleHttp\Mimetypes
has been moved to a function inGuzzleHttp\Psr7\mimetype_from_extension
andGuzzleHttp\Psr7\mimetype_from_filename
.GuzzleHttp\Query
and GuzzleHttp\QueryParser
have been removed. Queryquery
request option when creating requests with clients. The query
http_build_query
to convert an array to a string. If youGuzzleHttp\Psr7\parse_query
andGuzzleHttp\Psr7\build_query
.GuzzleHttp\Handler
namespace. This significantly reducesEvent
namespace.Subscriber
namespace.Transaction
classRequestFsm
RingBridge
GuzzleHttp\Subscriber\Cookie
is now provided byGuzzleHttp\Middleware::cookies
GuzzleHttp\Subscriber\HttpError
is now provided byGuzzleHttp\Middleware::httpError
GuzzleHttp\Subscriber\History
is now provided byGuzzleHttp\Middleware::history
GuzzleHttp\Subscriber\Mock
is now provided byGuzzleHttp\Handler\MockHandler
GuzzleHttp\Subscriber\Prepare
is now provided byGuzzleHttp\PrepareBodyMiddleware
GuzzleHttp\Subscriber\Redirect
is now provided byGuzzleHttp\RedirectMiddleware
Psr\Http\Message\UriInterface
(implements inGuzzleHttp\Psr7\Uri
) for URI support. GuzzleHttp\Url
is now gone.GuzzleHttp\Utils
have been moved to namespacedGuzzleHttp
namespace. This requires either a ComposerGuzzleHttp\ClientInterface::getDefaultOption
has been renamed toGuzzleHttp\ClientInterface::getConfig
.GuzzleHttp\ClientInterface::setDefaultOption
has been removed.json
and xml
methods of response objects has been removed. With theThe 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 anapplication/x-www-form-urlencoded
POST request. Themultipart
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 usemultipart
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 PHPcallable
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,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.
throwImmediately
has been removedThe 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 fromGuzzleHttp\Message\MessageInterface::getHeader
. If you want to get a header
value as an array, then use the newly added getHeaderAsArray()
method ofMessageInterface
. This change makes the Guzzle interfaces compatible with
the PSR-7 interfaces.
GuzzleHttp\Event\EmitterInterface
(resulting in significantChanges 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 foundGuzzleHttp\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 likesetPath
now supports appending to an existing array via the []
notation.Guzzle no longer requires Symfony's EventDispatcher component. Guzzle now usesGuzzleHttp\Event\Emitter
.
Symfony\Component\EventDispatcher\EventDispatcherInterface
is replaced byGuzzleHttp\Event\EmitterInterface
.Symfony\Component\EventDispatcher\EventDispatcher
is replaced byGuzzleHttp\Event\Emitter
.Symfony\Component\EventDispatcher\Event
is replaced byGuzzleHttp\Event\Event
, and Guzzle now has an EventInterface inGuzzleHttp\Event\EventInterface
.AbstractHasDispatcher
has moved to a trait, HasEmitterTrait
, andHasDispatcherInterface
has moved to HasEmitterInterface
. Retrieving thegetEmitter
methodgetDispatcher
method.once()
method to add a listener that automatically removes itselflisteners()
method to retrieve a list of event listeners rather thangetListeners()
method.emit()
instead of dispatch()
to emit an event from an emitter.attach()
instead of addSubscriber()
and detach()
instead ofremoveSubscriber()
.$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
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 infunctions.php
for an easy to use static client instance.GuzzleHttp\Exception
have been updated to all extend fromGuzzleHttp\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
tosetUserAgent()
has been removed. Use a default request option instead. You$client->setConfig('defaults/headers/User-Agent', 'Foo/Bar ' . $client::getDefaultUserAgent())
.setSslVerification()
has been removed. Use default request options instead,$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.defaults
key that is an associative array of defaultadapter
to use a custom adapter,batch_adapter
to use a custom adapter for sending requests in parallel, ormessage_factory
to change the factory used to create HTTP requests andclient.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 aGuzzleHttp\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
andGuzzleHttp\Message\EntityEnclosingRequestInterface
have been removed. TheGuzzleHttp\Message\RequestInterface
GuzzleHttp\Response
object now accept aGuzzleHttp\Message\ResponseInterface
.GuzzleHttp\Message\RequestFactoryInterface
has been renamed toGuzzleHttp\Message\MessageFactoryInterface
. This interface is used to createGuzzleHttp\Message\MessageFactory
.GuzzleHttp\Post\PostBodyInterface
GuzzleHttp\Message\MessageFactoryInterface
will automatically useGuzzleHttp\Post\PostBody
body if the body was passed as an array or if$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 simplytrue
to retrieve a header value as an arrayGuzzleHttp\PostFile
and GuzzleHttp\PostFileInterface
have been moved toGuzzleHttp\Post
. This interface has been simplified and now allows theGuzzleHttp\Message\Header\Link
have been removed. MostGuzzleHttp\Message\HeaderValues::parseParams()
hasLink
header).GuzzleHttp\Message\Response::getInfo()
andGuzzleHttp\Message\Response::setInfo()
have been removed. Use the eventGuzzleHttp\Message\Response::getRawHeaders()
has been removed.GuzzleHttp\Message\Response::getMessage()
has been removed.GuzzleHttp\Message\Response::calculateAge()
and other cache specificgetContentMd5()
have been removed.getHeader('Content-MD5')
instead.GuzzleHttp\Message\Response::setRequest()
andGuzzleHttp\Message\Response::getRequest()
have been removed. Use the eventGuzzleHttp\Message\Response::getRedirectCount()
has been removed. Use theGuzzleHttp\Message\Response::isSuccessful()
and other related methods havegetStatusCode()
instead.Streaming requests can now be created by a client directly, returning aGuzzleHttp\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 aallow_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 toGuzzleHttp\Stream
. All classes and interfaces that once requiredGuzzleHttp\EntityBodyInterface
now requireGuzzleHttp\Stream\StreamInterface
. Creating a new body for a request no
longer uses GuzzleHttp\EntityBody::factory
but now usesGuzzleHttp\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 customGuzzleHttp\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 aGuzzleHttp\Event\BeforeEvent
request.complete
has been renamed to complete
and now emits aGuzzleHttp\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
tocurl.callback.write
has been removed. Use a custom StreamInterface
tocurl.callback.read
has been removed. Use a custom StreamInterface
toheaders
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
, andGuzzleHttp\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
, andGuzzle\Iterator\MethodProxyIterator
are nice, but not a core requirement ofGuzzle\Iterator\FilterIterator
is no longer needed because an equivalentGuzzle\Iterator\MapIterator
is not really needed when using PHP 5.5 becauseFor a replacement of these iterators, see https://github.com/nikic/iter
The LogPlugin has moved to https://github.com/guzzle/log-subscriber. TheGuzzle\Log
namespace has been removed. Guzzle now relies onPsr\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 onlyGuzzleHttp\UriTemplate
. The Guzzle library will automatically use the PECLGuzzleHttp\Url::fromString
(previouslyGuzzle\Http\Url::factory()
). If custom URL parsing is necessary,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 jarGuzzleHttp\Cookie
.GuzzleHttp\Subscriber\History
: Replaces the old HistoryPlugin.GuzzleHttp\Subscriber\HttpError
: Throws errors when a bad HTTP response isGuzzleHttp\Subscriber\Mock
: Replaces the old MockPlugin.GuzzleHttp\Subscriber\Prepare
: Prepares the body of a request just beforeGuzzleHttp\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. ThisThe 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 simplerGuzzle\Http\Plugin\Cache\CachePlugin
has moved toGuzzle\Http\Plugin\Log\LogPlugin
has moved toGuzzle\Http\Plugin\Md5\Md5Plugin
has moved toGuzzle\Http\Plugin\Mock\MockPlugin
has moved toGuzzleHttp\Subscriber\MockSubscriber
.Guzzle\Http\Plugin\Oauth\OauthPlugin
has moved toThe 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
andGuzzle\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 ofGuzzleHttp\Stream\MetadataStreamInterface
.getWrapper
, getWrapperData
, getStreamType
, and getUri
have all beenGuzzleHttp\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 ofGuzzleHttp\Stream\Stream
.GuzzleHttp\Stream\MetadataStreamInterface
has been added to denote streams
that contain additional metadata accessible via getMetadata()
.GuzzleHttp\Stream\StreamInterface::getMetadata
andGuzzleHttp\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
:$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)
toGuzzle\Http\ClientInterface::get($uri = null, $headers = null, $options = array())
. You can still pass in aGuzzle\Common\Collection::__construct($data)
to no longer accepts a null value for $data
but aarray()
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 aGuzzle\Service\Command\ArrayCommandInterface
.Guzzle\Http\Message\RequestInterface::startResponse()
to the RequestInterface to handle injecting a responseGuzzle\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
Guzzle\Http\Utils
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()
orgetResponse()
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 09daeb8c666fb44499a0646d655a8ae36456575e)
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.