Permalink
Browse files

Adding the ability to specify default request options for every clien…

…t request

Adding Guzzle\Common\Collection::setPath($path, $value)
Marking setDefaultHeaders() and getDefaultHeaders() as deprecated on a
Client.
Added the ability to provide flags when applying RequestFactory options.
This allows for things like applying options in a default manner so that
they do not overwrite existing values.
  • Loading branch information...
1 parent cc28a95 commit e29fcc71fdd1787a2c310fbce308c9c947af7f3f @mtdowling mtdowling committed Jun 9, 2013
View
@@ -6,20 +6,23 @@ Next version
* New features:
- Requests now support the ability to specify an array of $options when creating a request to more easily modify a
- request
+ request. You can pass a 'request.options' configuration setting to a client to apply default request options to
+ every request created by a client (e.g. default query string variables, headers, curl options, etc).
- Added a static facade class that allows you to use Guzzle with static methods and mount the class to `\Guzzle`.
See `Guzzle\Http\StaticClient::mount`.
+ - Added `command.request_options` to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
+ created by a command (e.g. custom headers, query string variables, timeout settings, etc).
- Stream size in `Guzzle\Stream\PhpStreamRequestFactory` will now be set if Content-Length is returned in the
headers of a response
- - Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
- - Added command.request_options to `Guzzle\Service\Command\AbstractCommand` to pass request options to requests
- created by a command
- - `Guzzle\Http\Message\Response` now implements `\Serializable`
- - `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
+ - Added `Guzzle\Common\Collection::setPath($path, $value)` to set a value into an array using a nested key
+ (e.g. `$collection->setPath('foo/baz/bar', 'test'); echo $collection['foo']['bar']['bar'];`)
- ServiceBuilders now support storing and retrieving arbitrary data
- CachePlugin can now purge all resources for a given URI
- CachePlugin can automatically purge matching cached items when a non-idempotent request is sent to a resource
- CachePlugin now uses the Vary header to determine if a resource is a cache hit
+ - `Guzzle\Http\Message\Response` now implements `\Serializable`
+ - Added `Guzzle\Cache\CacheAdapterFactory::fromCache()` to more easily create cache adapters
+ - `Guzzle\Service\ClientInterface::execute()` now accepts an array, single command, or Traversable
* Bug fixes:
- Fixed a bug in `Guzzle\Http\Message\Header\Link::addLink()`
* Improvements:
@@ -44,7 +47,10 @@ Next version
- Added `Guzzle\Stream\StreamInterface::isRepeatable`
- 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:
- - Removed `Guzzle\Http\ClientInterface::setDefaultHeaders()`
+ - Removed `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'))`.
+ - Removed `Guzzle\Http\ClientInterface::getDefaultHeaders(). Use $client->getConfig()->getPath('request.options/headers')`.
- Removed `Guzzle\Http\ClientInterface::expandTemplate()`
- Removed `Guzzle\Http\ClientInterface::setRequestFactory()`
- Removed `Guzzle\Http\ClientInterface::getCurlMulti()`
@@ -65,8 +71,9 @@ Next version
- Marked `Guzzle\Cache\CacheAdapterFactory::factory()` as deprecated
- Marked 'command.headers', 'command.response_body' and 'command.on_complete' as deprecated for AbstractCommand.
These will work through Guzzle 4.0
- - Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated
- - Magic methods can no longer be disabled on a Guzzle\Service\Client
+ - Marked `Guzzle\Service\Client::enableMagicMethods()` as deprecated. Magic methods can no longer be disabled on a Guzzle\Service\Client.
+ - Marked `Guzzle\Service\Client::getDefaultHeaders()` as deprecated. Use $client->getConfig()->getPath('request.options/headers')`.
+ - Marked `Guzzle\Service\Client::setDefaultHeaders()` as deprecated. Use $client->getConfig()->setPath('request.options/headers/{header_name}', 'value')`.
- Marked `Guzzle\Parser\Url\UrlParser` as deprecated. Just use PHP's `parse_url()` and percent encode your UTF-8.
- Marked `Guzzle\Common\Collection::inject()` as deprecated.
* Breaking changes in the CachePlugin internals:
View
@@ -44,7 +44,7 @@
</target>
<target name="coverage" depends="prepare">
- <exec passthru="true" command="vendor/bin/phpunit --coverage-html=${dir.output}/coverage --coverage-clover=${dir.output}/logs/clover.xml" />
+ <exec passthru="true" command="vendor/bin/phpunit --coverage-html=${dir.output}/coverage" />
</target>
<target name="view-coverage">
@@ -3,6 +3,7 @@
namespace Guzzle\Common;
use Guzzle\Common\Exception\InvalidArgumentException;
+use Guzzle\Common\Exception\RuntimeException;
/**
* Key value pair collection object
@@ -311,22 +312,32 @@ public function offsetUnset($offset)
}
/**
- * Inject configuration settings into an input string
+ * Set a value into a nested array key. Keys will be created as needed to set the value.
*
- * @param string $input Input to inject
+ * @param string $path Path to set
+ * @param mixed $value Value to set at the key
*
- * @return string
- * @deprecated
+ * @return self
+ * @throws RuntimeException when trying to setPath using a nested path that travels through a scalar value
*/
- public function inject($input)
+ public function setPath($path, $value)
{
- Version::warn(__METHOD__ . ' is deprecated');
- $replace = array();
- foreach ($this->data as $key => $val) {
- $replace['{' . $key . '}'] = $val;
+ $current =& $this->data;
+ $queue = explode('/', $path);
+ while (null !== ($key = array_shift($queue))) {
+ if (!is_array($current)) {
+ throw new RuntimeException("Trying to setPath {$path}, but {$key} is set and is not an array");
+ } elseif (!$queue) {
+ $current[$key] = $value;
+ } elseif (isset($current[$key])) {
+ $current =& $current[$key];
+ } else {
+ $current[$key] = array();
+ $current =& $current[$key];
+ }
}
- return strtr($input, $replace);
+ return $this;
}
/**
@@ -344,7 +355,7 @@ public function getPath($path, $separator = '/', $data = null)
{
// Assume the data of the collection if no data was passed into the method
if ($data === null) {
- $data = &$this->data;
+ $data =& $this->data;
}
// Break the path into an array if needed
@@ -384,9 +395,28 @@ public function getPath($path, $separator = '/', $data = null)
}
// Descend deeper into the data
- $data = &$data[$part];
+ $data =& $data[$part];
}
return $data;
}
+
+ /**
+ * Inject configuration settings into an input string
+ *
+ * @param string $input Input to inject
+ *
+ * @return string
+ * @deprecated
+ */
+ public function inject($input)
+ {
+ Version::warn(__METHOD__ . ' is deprecated');
+ $replace = array();
+ foreach ($this->data as $key => $val) {
+ $replace['{' . $key . '}'] = $val;
+ }
+
+ return strtr($input, $replace);
+ }
}
View
@@ -23,6 +23,7 @@
*/
class Client extends AbstractHasDispatcher implements ClientInterface
{
+ const REQUEST_OPTIONS = 'request.options';
const REQUEST_PARAMS = 'request.params';
const CURL_OPTIONS = 'curl.options';
const SSL_CERT_AUTHORITY = 'ssl.certificate_authority';
@@ -70,19 +71,14 @@ public function __construct($baseUrl = '', $config = null)
$this->setBaseUrl($baseUrl);
$this->defaultHeaders = new Collection();
$this->setRequestFactory(RequestFactory::getInstance());
-
- // Redirect by default, but allow for redire4cts to be globally disabled on a client
+ $this->userAgent = $this->getDefaultUserAgent();
if (!$this->config[self::DISABLE_REDIRECTS]) {
$this->addSubscriber(new RedirectPlugin());
}
-
- // Set the default User-Agent on the client
- $this->userAgent = $this->getDefaultUserAgent();
}
final public function setConfig($config)
{
- // Set the configuration object
if ($config instanceof Collection) {
$this->config = $config;
} elseif (is_array($config)) {
@@ -137,24 +133,6 @@ public function __construct($baseUrl = '', $config = null)
return $this;
}
- public function getDefaultHeaders()
- {
- return $this->defaultHeaders;
- }
-
- public function setDefaultHeaders($headers)
- {
- if ($headers instanceof Collection) {
- $this->defaultHeaders = $headers;
- } elseif (is_array($headers)) {
- $this->defaultHeaders = new Collection($headers);
- } else {
- throw new InvalidArgumentException('Headers must be an array or Collection');
- }
-
- return $this;
- }
-
public function expandTemplate($template, array $variables = null)
{
$expansionVars = $this->getConfig()->toArray();
@@ -211,11 +189,10 @@ public function createRequest($method = 'GET', $uri = null, $headers = null, $bo
}
}
- // If default headers are provided, then merge them into existing headers
- // If a collision occurs, the header is completely replaced
+ // If default headers are provided, then merge them under any explicitly provided headers for the request
if (count($this->defaultHeaders)) {
if (!$headers) {
- $headers = $this->defaultHeaders;
+ $headers = $this->defaultHeaders->toArray();
} elseif (is_array($headers)) {
$headers += $this->defaultHeaders->toArray();
} elseif ($headers instanceof Collection) {
@@ -402,26 +379,24 @@ protected function sendMultiple(array $requests)
*/
protected function prepareRequest(RequestInterface $request, array $options = array())
{
- $request->setClient($this);
+ $request->setClient($this)->setEventDispatcher(clone $this->getEventDispatcher());
- // Add any curl options to the request
if ($curl = $this->config[self::CURL_OPTIONS]) {
$request->getCurlOptions()->overwriteWith(CurlHandle::parseCurlConfig($curl));
}
- // Add request parameters to the request
if ($params = $this->config[self::REQUEST_PARAMS]) {
$request->getParams()->overwriteWith($params);
}
- // Attach client observers to the request
- $request->setEventDispatcher(clone $this->getEventDispatcher());
-
- // Set the User-Agent if one is specified on the client but not explicitly on the request
if ($this->userAgent && !$request->hasHeader('User-Agent')) {
$request->setHeader('User-Agent', $this->userAgent);
}
+ if ($defaults = $this->config[self::REQUEST_OPTIONS]) {
+ $this->requestFactory->applyOptions($request, $defaults, RequestFactoryInterface::OPTIONS_AS_DEFAULTS);
+ }
+
if ($options) {
$this->requestFactory->applyOptions($request, $options);
}
@@ -436,30 +411,50 @@ protected function prepareRequest(RequestInterface $request, array $options = ar
*/
protected function initSsl()
{
- // Allow ssl.certificate_authority config setting to control the certificate authority used by curl
- $authority = $this->config[self::SSL_CERT_AUTHORITY];
+ if ('system' == ($authority = $this->config[self::SSL_CERT_AUTHORITY])) {
+ return;
+ }
- // Set the SSL certificate
- if ($authority !== 'system') {
+ if ($authority === null) {
+ $authority = true;
+ }
- if ($authority === null) {
- $authority = true;
- }
+ if ($authority === true && substr(__FILE__, 0, 7) == 'phar://') {
+ $authority = $this->preparePharCacert();
+ $that = $this;
+ $this->getEventDispatcher()->addListener('request.before_send', function ($event) use ($authority, $that) {
+ if ($authority == $event['request']->getCurlOptions()->get(CURLOPT_CAINFO)) {
+ $that->preparePharCacert(false);
+ }
+ });
+ }
- if ($authority === true && substr(__FILE__, 0, 7) == 'phar://') {
- $authority = $this->preparePharCacert();
- $that = $this;
- $this->getEventDispatcher()->addListener(
- 'request.before_send',
- function ($event) use ($authority, $that) {
- if ($authority == $event['request']->getCurlOptions()->get(CURLOPT_CAINFO)) {
- $that->preparePharCacert(false);
- }
- }
- );
- }
+ $this->setSslVerification($authority);
+ }
+
+ /**
+ * @deprecated
+ */
+ public function getDefaultHeaders()
+ {
+ Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to retrieve default request options');
+ return $this->defaultHeaders;
+ }
- $this->setSslVerification($authority);
+ /**
+ * @deprecated
+ */
+ public function setDefaultHeaders($headers)
+ {
+ Version::warn(__METHOD__ . ' is deprecated. Use the request.options array to specify default request options');
+ if ($headers instanceof Collection) {
+ $this->defaultHeaders = $headers;
+ } elseif (is_array($headers)) {
+ $this->defaultHeaders = new Collection($headers);
+ } else {
+ throw new InvalidArgumentException('Headers must be an array or Collection');
}
+
+ return $this;
}
}
@@ -21,18 +21,28 @@
/**
* Set the configuration object to use with the client
*
- * @param array|Collection|string $config Parameters that define how the client behaves and connects to a
- * webservice. Pass an array or a Collection object.
+ * @param array|Collection $config Parameters that define how the client behaves
+ *
* @return self
*/
public function setConfig($config);
/**
- * Get a configuration setting or all of the configuration settings
+ * Get a configuration setting or all of the configuration settings. The Collection result of this method can be
+ * modified to change the configuration settings of a client.
+ *
+ * A client should honor the following special values:
+ *
+ * - request.options: Associative array of default RequestFactory options to apply to each request
+ * - request.params: Associative array of request parameters (data values) to apply to each request
+ * - curl.options: Associative array of cURL configuration settings to apply to each request
+ * - ssl.certificate_authority: Path a CAINFO, CAPATH, true to use strict defaults, or false to disable verification
+ * - redirect.disable: Set to true to disable redirects
*
* @param bool|string $key Configuration value to retrieve. Set to FALSE to retrieve all values of the client.
* The object return can be modified, and modifications will affect the client's config.
* @return mixed|Collection
+ * @see \Guzzle\Http\Message\RequestFactoryInterface::applyOptions for a full list of request.options options
*/
public function getConfig($key = false);
@@ -161,13 +171,6 @@ public function options($uri = null, array $options = array());
*/
public function send($requests);
- /**
- * Get the default HTTP headers to add to each request created by the client
- *
- * @return Collection
- */
- public function getDefaultHeaders();
-
/**
* Get the client's base URL as either an expanded or raw URI template
*
Oops, something went wrong.

0 comments on commit e29fcc7

Please sign in to comment.