mirror of
https://github.com/guzzle/guzzle.git
synced 2025-01-17 21:38:16 +01:00
Adding support for URI templates
[Http] UriTemplate syntax supports {} or {{}} for backwards compatibility. [Http] Guzzle::inject() now allows {} or {{}} injection for consistency. [Http] BC: removing Guzzle\Http\Client::inject and now using Guzzle\Http\Client::expandTemplate. [Http] Can use a custom syntax for URI templates (this might be useful for something like Solr because Solr actually uses {}). [Http] Adding the ability to inject a custom UriTemplate into clients or just use the default UriTemplate [Http] You can now use an array when creating a request via a client to specify a URI template and additional template variables. [Service] Adding support for URI templates to service descriptions. [Service] [BC] removing Guzzle\Service\Description\ApiCommand::getPath() and replacing it with getUri(). [Service] Use "uri" instead of "path" when creating service descriptions. However, there is still backwards compatibility with the "path" attribute.
This commit is contained in:
parent
4685aed7ef
commit
b9c04909c7
39
README.md
39
README.md
@ -31,6 +31,7 @@ Features
|
||||
- Subject/Observer signal slot system for unobtrusively modifying request behavior
|
||||
- Supports all of the features of libcurl including authentication, redirects, SSL, proxies, etc
|
||||
- Web service client framework for building future-proof interfaces to web services
|
||||
- Full support for [URI templates](http://tools.ietf.org/html/draft-gregorio-uritemplate-08)
|
||||
|
||||
HTTP basics
|
||||
-----------
|
||||
@ -118,6 +119,44 @@ try {
|
||||
}
|
||||
```
|
||||
|
||||
URI templates
|
||||
-------------
|
||||
|
||||
Guzzle supports the entire URI templates RFC.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$client = new Guzzle\Http\Client('http://www.myapi.com/api/v1', array(
|
||||
'path' => '/path/to',
|
||||
'a' => 'hi',
|
||||
'data' => array(
|
||||
'foo' => 'bar',
|
||||
'mesa' => 'jarjar'
|
||||
)
|
||||
));
|
||||
|
||||
$request = $client->get('http://www.test.com{+path}{?a,data*}');
|
||||
```
|
||||
|
||||
The generated request URL would become: ``http://www.test.com/path/to?a=hi&foo=bar&mesa=jarajar``
|
||||
|
||||
You can specify URI templates and an array of additional template variables to use when creating requests:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
$client = new Guzzle\Http\Client('http://test.com', array(
|
||||
'a' => 'hi'
|
||||
));
|
||||
|
||||
$request = $client->get(array('/{?a,b}', array(
|
||||
'b' => 'there'
|
||||
));
|
||||
```
|
||||
|
||||
The resulting URL would become ``http://test.com?a=hi&b=there``
|
||||
|
||||
Testing Guzzle
|
||||
--------------
|
||||
|
||||
|
@ -91,12 +91,7 @@ class Guzzle
|
||||
*/
|
||||
public static function inject($input, Collection $config)
|
||||
{
|
||||
// Skip expensive regular expressions if it isn't needed
|
||||
if (strpos($input, '{{') === false) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
return preg_replace_callback('/{{\s*([A-Za-z_\-\.0-9]+)\s*}}/', function($matches) use ($config) {
|
||||
return preg_replace_callback('/{{1,2}\s*([A-Za-z_\-\.0-9]+)\s*}{1,2}/', function($matches) use ($config) {
|
||||
return $config->get(trim($matches[1]));
|
||||
}, $input
|
||||
);
|
||||
|
@ -7,6 +7,7 @@ use Guzzle\Common\AbstractHasDispatcher;
|
||||
use Guzzle\Common\ExceptionCollection;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Http\Url;
|
||||
use Guzzle\Http\UriTemplate;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\Message\RequestInterface;
|
||||
use Guzzle\Http\Message\RequestFactory;
|
||||
@ -39,6 +40,11 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
*/
|
||||
private $curlMulti;
|
||||
|
||||
/**
|
||||
* @var UriTemplate URI template owned by the client
|
||||
*/
|
||||
private $uriTemplate;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@ -107,41 +113,91 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject configuration values into a formatted string with {{param}} as a
|
||||
* parameter delimiter (replace param with the configuration value name)
|
||||
* Expand a URI template using client configuration data
|
||||
*
|
||||
* @param string $string String to inject config values into
|
||||
* @param string $template URI template to expand
|
||||
* @param array $variables (optional) Additional variables to use in the expansion
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public final function inject($string)
|
||||
public function expandTemplate($template, array $variables = null)
|
||||
{
|
||||
return Guzzle::inject($string, $this->getConfig());
|
||||
$expansionVars = $this->getConfig()->getAll();
|
||||
if ($variables) {
|
||||
$expansionVars = array_merge($expansionVars, $variables);
|
||||
}
|
||||
|
||||
return $this->getUriTemplate()
|
||||
->setTemplate($template)
|
||||
->expand($expansionVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URI template expander to use with the client
|
||||
*
|
||||
* @param UriTemplate $uriTemplate
|
||||
*
|
||||
* @return Client
|
||||
*/
|
||||
public function setUriTemplate(UriTemplate $uriTemplate)
|
||||
{
|
||||
$this->uriTemplate = $uriTemplate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI template expander used by the client. A default UriTemplate
|
||||
* object will be created if one does not exist.
|
||||
*
|
||||
* @return UriTemplate
|
||||
*/
|
||||
public function getUriTemplate()
|
||||
{
|
||||
if (!$this->uriTemplate) {
|
||||
$this->uriTemplate = new UriTemplate();
|
||||
}
|
||||
|
||||
return $this->uriTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a new {@see RequestInterface} configured for the client
|
||||
*
|
||||
* @param string $method (optional) HTTP method. Defaults to GET
|
||||
* @param string $uri (optional) Resource URI. Use an absolute path to
|
||||
* override the base path of the client, or a relative path to append
|
||||
* to the base path of the client. The URI can contain the
|
||||
* querystring as well.
|
||||
* @param string|array $uri (optional) Resource URI. Use an absolute path
|
||||
* to override the base path of the client, or a relative path to
|
||||
* append to the base path of the client. The URI can contain the
|
||||
* querystring as well. Use an array to provide a URI template and
|
||||
* additional variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param string|resource|array|EntityBody $body (optional) Entity body of
|
||||
* request (POST/PUT) or response (GET)
|
||||
*
|
||||
* @return RequestInterface
|
||||
* @throws InvalidArgumentException if a URI array is passed that does not
|
||||
* contain exactly two elements: the URI followed by template variables
|
||||
*/
|
||||
public function createRequest($method = RequestInterface::GET, $uri = null, $headers = null, $body = null)
|
||||
{
|
||||
if (!is_array($uri)) {
|
||||
$templateVars = null;
|
||||
} else {
|
||||
if (count($uri) != 2 || !is_array($uri[1])) {
|
||||
throw new \InvalidArgumentException('You must provide a URI'
|
||||
. ' template followed by an array of template variables'
|
||||
. ' when using an array for a URI template');
|
||||
}
|
||||
list($uri, $templateVars) = $uri;
|
||||
}
|
||||
|
||||
if (!$uri) {
|
||||
$url = $this->getBaseUrl();
|
||||
} else if (strpos($uri, 'http') === 0) {
|
||||
// Use absolute URLs as-is
|
||||
$url = $this->inject($uri);
|
||||
$url = $this->expandTemplate($uri, $templateVars);
|
||||
} else {
|
||||
$url = Url::factory($this->getBaseUrl())->combine($this->inject($uri));
|
||||
$url = Url::factory($this->getBaseUrl())->combine($this->expandTemplate($uri, $templateVars));
|
||||
}
|
||||
|
||||
return $this->prepareRequest(
|
||||
@ -193,20 +249,20 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the base service endpoint URL with configuration options injected
|
||||
* into the configuration setting.
|
||||
* Get the client's base URL as either an expanded or raw URI template
|
||||
*
|
||||
* @param bool $inject (optional) Set to FALSE to get the raw base URL
|
||||
* @param bool $expand (optional) Set to FALSE to get the raw base URL
|
||||
* without URI template expansion
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getBaseUrl($inject = true)
|
||||
public function getBaseUrl($expand = true)
|
||||
{
|
||||
return $inject ? $this->inject($this->baseUrl) : $this->baseUrl;
|
||||
return $expand ? $this->expandTemplate($this->baseUrl) : $this->baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base service endpoint URL
|
||||
* Set the base URL of the client
|
||||
*
|
||||
* @param string $url The base service endpoint URL of the webservice
|
||||
*
|
||||
@ -242,24 +298,28 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
/**
|
||||
* Create a GET request for the client
|
||||
*
|
||||
* @param string $path (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param string|resource|array|EntityBody $body (optional) Where to store
|
||||
* the response entity body
|
||||
*
|
||||
* @return Request
|
||||
*/
|
||||
public final function get($path = null, $headers = null, $body = null)
|
||||
public final function get($uri = null, $headers = null, $body = null)
|
||||
{
|
||||
return $this->createRequest('GET', $path, $headers, $body);
|
||||
return $this->createRequest('GET', $uri, $headers, $body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a HEAD request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
*
|
||||
* @return Request
|
||||
@ -272,8 +332,10 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
/**
|
||||
* Create a DELETE request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
*
|
||||
* @return Request
|
||||
@ -286,8 +348,10 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
/**
|
||||
* Create a PUT request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param string|resource|array|EntityBody $body Body to send in the request
|
||||
*
|
||||
@ -301,8 +365,10 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
/**
|
||||
* Create a POST request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an absolute path to
|
||||
* override the base path, or a relative path to append it.
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param array|Collection|string|EntityBody $postBody (optional) POST
|
||||
* body. Can be a string, EntityBody, or associative array of POST
|
||||
@ -319,8 +385,10 @@ class Client extends AbstractHasDispatcher implements ClientInterface
|
||||
/**
|
||||
* Create an OPTIONS request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
*
|
||||
* @return Request
|
||||
*/
|
||||
|
@ -36,23 +36,39 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
function getConfig($key = false);
|
||||
|
||||
/**
|
||||
* Inject configuration values into a formatted string with {{param}} as a
|
||||
* parameter delimiter (replace param with the configuration value name)
|
||||
* Set the URI template expander to use with the client
|
||||
*
|
||||
* @param string $string String to inject config values into
|
||||
* @param UriTemplate $uriTemplate
|
||||
*
|
||||
* @return ClientInterface
|
||||
*/
|
||||
function setUriTemplate(UriTemplate $uriTemplate);
|
||||
|
||||
/**
|
||||
* Get the URI template expander used by the client
|
||||
*
|
||||
* @return UriTemplate
|
||||
*/
|
||||
function getUriTemplate();
|
||||
|
||||
/**
|
||||
* Expand a URI template using client configuration data
|
||||
*
|
||||
* @param string $template URI template to expand
|
||||
* @param array $variables (optional) Additional variables to use in the expansion
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function inject($string);
|
||||
function expandTemplate($template, array $variables = null);
|
||||
|
||||
/**
|
||||
* Create and return a new {@see RequestInterface} configured for the client
|
||||
*
|
||||
* @param string $method (optional) HTTP method. Defaults to GET
|
||||
* @param string $uri (optional) Resource URI. Use an absolute path to
|
||||
* override the base path of the client, or a relative path to append
|
||||
* to the base path of the client. The URI can contain the
|
||||
* querystring as well.
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param string|resource|array|EntityBody $body (optional) Entity body of
|
||||
* request (POST/PUT) or response (GET)
|
||||
@ -76,18 +92,17 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
function prepareRequest(RequestInterface $request);
|
||||
|
||||
/**
|
||||
* Get the base service endpoint URL with configuration options injected
|
||||
* into the configuration setting.
|
||||
* Get the client's base URL as either an expanded or raw URI template
|
||||
*
|
||||
* @param bool $inject (optional) Set to FALSE to get the raw base URL
|
||||
* @param bool $expand (optional) Set to FALSE to get the raw base URL
|
||||
* without URI template expansion
|
||||
*
|
||||
* @return string
|
||||
* @throws RuntimeException if a base URL has not been set
|
||||
*/
|
||||
function getBaseUrl($inject = true);
|
||||
function getBaseUrl($expand = true);
|
||||
|
||||
/**
|
||||
* Set the base service endpoint URL
|
||||
* Set the base URL of the client
|
||||
*
|
||||
* @param string $url The base service endpoint URL of the webservice
|
||||
*
|
||||
@ -110,8 +125,10 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
/**
|
||||
* Create a GET request for the client
|
||||
*
|
||||
* @param string $path (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param string|resource|array|EntityBody $body (optional) Where to store
|
||||
* the response entity body
|
||||
@ -123,8 +140,10 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
/**
|
||||
* Create a HEAD request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
*
|
||||
* @return RequestInterface
|
||||
@ -134,8 +153,10 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
/**
|
||||
* Create a DELETE request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
*
|
||||
* @return RequestInterface
|
||||
@ -145,8 +166,10 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
/**
|
||||
* Create a PUT request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param string|resource|array|EntityBody $body Body to send in the request
|
||||
*
|
||||
@ -157,8 +180,10 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
/**
|
||||
* Create a POST request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an absolute path to
|
||||
* override the base path, or a relative path to append it.
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
* @param array|Collection $headers (optional) HTTP headers
|
||||
* @param array|Collection|string|EntityBody $postBody (optional) POST
|
||||
* body. Can be a string, EntityBody, or associative array of POST
|
||||
@ -172,8 +197,10 @@ interface ClientInterface extends HasDispatcherInterface
|
||||
/**
|
||||
* Create an OPTIONS request for the client
|
||||
*
|
||||
* @param string $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or relative path to append
|
||||
* @param string|array $uri (optional) Resource URI of the request. Use an
|
||||
* absolute path to override the base path, or a relative path to
|
||||
* append. Use an array to provide a URI template and additional
|
||||
* variables to use in the URI template expansion.
|
||||
*
|
||||
* @return RequestInterface
|
||||
*/
|
||||
|
252
src/Guzzle/Http/UriTemplate.php
Normal file
252
src/Guzzle/Http/UriTemplate.php
Normal file
@ -0,0 +1,252 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Http;
|
||||
|
||||
/**
|
||||
* Expands URI templates using an array of variables
|
||||
*
|
||||
* @link http://tools.ietf.org/html/draft-gregorio-uritemplate-08
|
||||
*/
|
||||
class UriTemplate
|
||||
{
|
||||
private $template;
|
||||
private $variables;
|
||||
private $regex = '/\{{1,2}([^\}]+)\}{1,2}/';
|
||||
private static $operators = array('+', '#', '.', '/', ';', '?', '&');
|
||||
private static $delims = array(':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=');
|
||||
private static $delimsPct = array('%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D');
|
||||
|
||||
/**
|
||||
* @param string $template (optional) URI template to expand
|
||||
*/
|
||||
public function __construct($template = '')
|
||||
{
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URI template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate()
|
||||
{
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the URI template
|
||||
*
|
||||
* @param string $template URI template to expand
|
||||
*
|
||||
* @return UriTemplate
|
||||
*/
|
||||
public function setTemplate($template)
|
||||
{
|
||||
$this->template = $template;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the URI template using the supplied variables
|
||||
*
|
||||
* @param array $variables Variables to use with the expansion
|
||||
*
|
||||
* @return string Returns the expanded template
|
||||
*/
|
||||
public function expand(array $variables)
|
||||
{
|
||||
$this->variables = $variables;
|
||||
|
||||
return preg_replace_callback($this->regex, array($this, 'expandMatch'), $this->template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the regular expression used to identify URI templates
|
||||
*
|
||||
* @param string $regex Regular expression
|
||||
*
|
||||
* @return UriTemplate
|
||||
*/
|
||||
public function setRegex($regex)
|
||||
{
|
||||
$this->regex = $regex;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an expression into parts
|
||||
*
|
||||
* @param string $expression Expression to parse
|
||||
*
|
||||
* @return array Returns an associative array of parts
|
||||
*/
|
||||
private function parseExpression($expression)
|
||||
{
|
||||
// Check for URI operators
|
||||
$operator = '';
|
||||
if (in_array($expression[0], self::$operators)) {
|
||||
$operator = $expression[0];
|
||||
$expression = substr($expression, 1);
|
||||
}
|
||||
|
||||
return array(
|
||||
'operator' => $operator,
|
||||
'values' => array_map(function($value) {
|
||||
$value = trim($value);
|
||||
$varspec = array();
|
||||
$substrPos = strpos($value, ':');
|
||||
if ($substrPos) {
|
||||
$varspec['value'] = substr($value, 0, $substrPos);
|
||||
$varspec['modifier'] = ':';
|
||||
$varspec['position'] = (int) substr($value, $substrPos + 1);
|
||||
} else if (substr($value, -1) == '*') {
|
||||
$varspec['modifier'] = '*';
|
||||
$varspec['value'] = substr($value, 0, -1);
|
||||
} else {
|
||||
$varspec['value'] = (string) $value;
|
||||
$varspec['modifier'] = '';
|
||||
}
|
||||
return $varspec;
|
||||
}, explode(',', $expression))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an expansion
|
||||
*
|
||||
* @param array $matches Matches met in the preg_replace_callback
|
||||
*
|
||||
* @return string Returns the replacement string
|
||||
*/
|
||||
private function expandMatch(array $matches)
|
||||
{
|
||||
$parsed = self::parseExpression($matches[1]);
|
||||
$replacements = array();
|
||||
|
||||
$prefix = $parsed['operator'];
|
||||
$joiner = $parsed['operator'];
|
||||
$useQueryString = false;
|
||||
if ($parsed['operator'] == '?') {
|
||||
$joiner = '&';
|
||||
$useQueryString = true;
|
||||
} else if ($parsed['operator'] == '&') {
|
||||
$useQueryString = true;
|
||||
} else if ($parsed['operator'] == '#') {
|
||||
$joiner = ',';
|
||||
} else if ($parsed['operator'] == ';') {
|
||||
$useQueryString = true;
|
||||
} else if ($parsed['operator'] == '' || $parsed['operator'] == '+') {
|
||||
$joiner = ',';
|
||||
$prefix = '';
|
||||
}
|
||||
|
||||
foreach ($parsed['values'] as $value) {
|
||||
|
||||
if (!array_key_exists($value['value'], $this->variables)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$variable = $this->variables[$value['value']];
|
||||
$actuallyUseQueryString = $useQueryString;
|
||||
$expanded = '';
|
||||
|
||||
if (is_array($variable)) {
|
||||
|
||||
$isAssoc = $this->isAssoc($variable);
|
||||
$kvp = array();
|
||||
foreach ($variable as $key => $var) {
|
||||
if ($isAssoc) {
|
||||
$key = rawurlencode($key);
|
||||
}
|
||||
$var = rawurlencode($var);
|
||||
if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
|
||||
$var = $this->decodeReserved($var);
|
||||
}
|
||||
|
||||
if ($value['modifier'] == '*') {
|
||||
if ($isAssoc) {
|
||||
$var = $key . '=' . $var;
|
||||
} else if ($key > 0 && $actuallyUseQueryString) {
|
||||
$var = $value['value'] . '=' . $var;
|
||||
}
|
||||
}
|
||||
|
||||
$kvp[$key] = $var;
|
||||
}
|
||||
|
||||
if ($value['modifier'] == '*') {
|
||||
$expanded = implode($joiner, $kvp);
|
||||
if ($isAssoc) {
|
||||
// Don't prepend the value name when using the explode
|
||||
// modifier with an associative array
|
||||
$actuallyUseQueryString = false;
|
||||
}
|
||||
} else {
|
||||
if ($isAssoc) {
|
||||
// When an associative array is encountered and the
|
||||
// explode modifier is not set, then the result must
|
||||
// be a comma separated list of keys followed by their
|
||||
// respective values.
|
||||
foreach ($kvp as $k => &$v) {
|
||||
$v = $k . ',' . $v;
|
||||
}
|
||||
}
|
||||
$expanded = implode(',', $kvp);
|
||||
}
|
||||
|
||||
} else {
|
||||
if ($value['modifier'] == ':') {
|
||||
$variable = substr($variable, 0, $value['position']);
|
||||
}
|
||||
$expanded = rawurlencode($variable);
|
||||
if ($parsed['operator'] == '+' || $parsed['operator'] == '#') {
|
||||
$expanded = $this->decodeReserved($expanded);
|
||||
}
|
||||
}
|
||||
|
||||
if ($actuallyUseQueryString) {
|
||||
if (!$expanded && $joiner != '&') {
|
||||
$expanded = $value['value'];
|
||||
} else {
|
||||
$expanded = $value['value'] . '=' . $expanded;
|
||||
}
|
||||
}
|
||||
|
||||
$replacements[] = $expanded;
|
||||
}
|
||||
|
||||
$ret = implode($joiner, $replacements);
|
||||
if ($ret && $prefix) {
|
||||
return $prefix . $ret;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if an array is associative
|
||||
*
|
||||
* @param array $array Array to check
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isAssoc(array $array)
|
||||
{
|
||||
return (bool) count(array_filter(array_keys($array), 'is_string'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes percent encoding on reserved characters (used with + and # modifiers)
|
||||
*
|
||||
* @param string $string String to fix
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function decodeReserved($string)
|
||||
{
|
||||
return str_replace(self::$delimsPct, self::$delims, $string);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ namespace Guzzle\Service\Command;
|
||||
use Guzzle\Guzzle;
|
||||
use Guzzle\Http\EntityBody;
|
||||
use Guzzle\Http\Url;
|
||||
use Guzzle\Http\UriTemplate;
|
||||
use Guzzle\Service\Inspector;
|
||||
|
||||
/**
|
||||
@ -27,28 +28,25 @@ class DynamicCommand extends AbstractCommand
|
||||
*/
|
||||
protected function build()
|
||||
{
|
||||
// Get the path values and use the client config settings
|
||||
$pathValues = $this->getClient()->getConfig();
|
||||
$foundPath = false;
|
||||
foreach ($this->apiCommand->getParams() as $name => $arg) {
|
||||
if ($arg->get('location') == 'path') {
|
||||
$pathValues->set($name, $arg->get('prepend') . $this->get($name) . $arg->get('append'));
|
||||
$foundPath = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Build a custom URL if there are path values
|
||||
if ($foundPath) {
|
||||
$path = str_replace('//', '', Guzzle::inject($this->apiCommand->getPath(), $pathValues));
|
||||
} else {
|
||||
$path = $this->apiCommand->getPath();
|
||||
}
|
||||
|
||||
if (!$path) {
|
||||
if (!$this->apiCommand->getUri()) {
|
||||
$url = $this->getClient()->getBaseUrl();
|
||||
} else {
|
||||
|
||||
// Get the path values and use the client config settings
|
||||
$variables = $this->getClient()->getConfig()->getAll();
|
||||
foreach ($this->apiCommand->getParams() as $name => $arg) {
|
||||
if (is_scalar($this->get($name))) {
|
||||
$variables[$name] = $arg->get('prepend') . $this->get($name) . $arg->get('append');
|
||||
}
|
||||
}
|
||||
|
||||
// Expand the URI template using the URI values
|
||||
$template = new UriTemplate($this->apiCommand->getUri());
|
||||
$uri = $template->expand($variables);
|
||||
|
||||
// Merge the client's base URL with the URI template
|
||||
$url = Url::factory($this->getClient()->getBaseUrl());
|
||||
$url->combine($path);
|
||||
$url->combine($uri);
|
||||
$url = (string) $url;
|
||||
}
|
||||
|
||||
@ -61,11 +59,7 @@ class DynamicCommand extends AbstractCommand
|
||||
if ($this->get($name)) {
|
||||
|
||||
// Check that a location is set
|
||||
$location = $arg->get('location') ?: 'query';
|
||||
|
||||
if ($location == 'path' || $location == 'data') {
|
||||
continue;
|
||||
}
|
||||
$location = $arg->get('location');
|
||||
|
||||
if ($location) {
|
||||
|
||||
|
@ -26,7 +26,7 @@ class ApiCommand
|
||||
* string name Name of the command
|
||||
* string doc Method documentation
|
||||
* string method HTTP method of the command
|
||||
* string path (optional) Path routing information of the command to include in the path
|
||||
* string uri (optional) URI routing information of the command
|
||||
* string class (optional) Concrete class that implements this command
|
||||
* array params Associative array of parameters for the command with each
|
||||
* parameter containing the following keys:
|
||||
@ -51,7 +51,12 @@ class ApiCommand
|
||||
$this->config['name'] = isset($config['name']) ? trim($config['name']) : '';
|
||||
$this->config['doc'] = isset($config['doc']) ? trim($config['doc']) : '';
|
||||
$this->config['method'] = isset($config['method']) ? trim($config['method']) : '';
|
||||
$this->config['path'] = isset($config['path']) ? trim($config['path']) : '';
|
||||
$this->config['uri'] = isset($config['uri']) ? trim($config['uri']) : '';
|
||||
if (!$this->config['uri']) {
|
||||
// Add backwards compatibility with the path attribute
|
||||
$this->config['uri'] = isset($config['path']) ? trim($config['path']) : '';
|
||||
}
|
||||
|
||||
$this->config['class'] = isset($config['class']) ? trim($config['class']) : 'Guzzle\\Service\\Command\\DynamicCommand';
|
||||
|
||||
if (isset($config['params']) && is_array($config['params'])) {
|
||||
@ -136,13 +141,12 @@ class ApiCommand
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the path routing information to append to the path of the generated
|
||||
* request
|
||||
* Get the URI that will be merged into the generated request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getPath()
|
||||
public function getUri()
|
||||
{
|
||||
return $this->config['path'];
|
||||
return $this->config['uri'];
|
||||
}
|
||||
}
|
@ -279,7 +279,7 @@ class Inspector
|
||||
}
|
||||
|
||||
// Inject configuration information into the config value
|
||||
if (is_scalar($config->get($name)) && strpos($config->get($name), '{{') !== false) {
|
||||
if (is_scalar($config->get($name)) && strpos($config->get($name), '{') !== false) {
|
||||
$config->set($name, Guzzle::inject($config->get($name), $config));
|
||||
}
|
||||
|
||||
|
@ -133,8 +133,8 @@ class ServiceBuilder implements \ArrayAccess
|
||||
|
||||
// Convert references to the actual client
|
||||
foreach ($this->builderConfig[$name]['params'] as $k => &$v) {
|
||||
if (0 === strpos($v, '{{') && strlen($v) - 2 == strpos($v, '}}')) {
|
||||
$v = $this->get(trim(substr($v, 2, -2)));
|
||||
if (0 === strpos($v, '{') && strlen($v) - 1 == strrpos($v, '}')) {
|
||||
$v = $this->get(trim(str_replace(array('{', '}'), '', $v)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,6 +50,7 @@ class GuzzleTest extends GuzzleTestCase
|
||||
'abc' => 'this'
|
||||
)),
|
||||
array('_is_a_', '{{ abc }}_is_{{ not_found }}a_{{ 0 }}', array()),
|
||||
array('_is_a_', '{abc}_is_{not_found}a_{{0}}', array()),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ namespace Guzzle\Tests\Http;
|
||||
use Guzzle\Guzzle;
|
||||
use Guzzle\Common\Collection;
|
||||
use Guzzle\Common\Log\ClosureLogAdapter;
|
||||
use Guzzle\Http\UriTemplate;
|
||||
use Guzzle\Http\Message\Response;
|
||||
use Guzzle\Http\Message\RequestFactory;
|
||||
use Guzzle\Http\Plugin\ExponentialBackoffPlugin;
|
||||
@ -101,7 +102,7 @@ class ClientTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
/**
|
||||
* @covers Guzzle\Http\Client
|
||||
*/
|
||||
public function testInjectConfig()
|
||||
public function testExpandsUriTemplatesUsingConfig()
|
||||
{
|
||||
$client = new Client('http://www.google.com/');
|
||||
$client->setConfig(array(
|
||||
@ -109,7 +110,7 @@ class ClientTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
'key' => 'value',
|
||||
'foo' => 'bar'
|
||||
));
|
||||
$this->assertEquals('Testing...api/v1/key/value', $client->inject('Testing...api/{{api}}/key/{{key}}'));
|
||||
$this->assertEquals('Testing...api/v1/key/value', $client->expandTemplate('Testing...api/{api}/key/{{key}}'));
|
||||
|
||||
// Make sure that the client properly validates and injects config
|
||||
$this->assertEquals('bar', $client->getConfig('foo'));
|
||||
@ -429,4 +430,114 @@ class ClientTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
$client->getEventDispatcher()->addSubscriber($mock);
|
||||
$client->send(array($client->get(), $client->head()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client
|
||||
*/
|
||||
public function testQueryStringsAreNotDoubleEncoded()
|
||||
{
|
||||
$client = new Client('http://test.com', array(
|
||||
'path' => array('foo', 'bar'),
|
||||
'query' => 'hi there',
|
||||
'data' => array(
|
||||
'test' => 'a&b'
|
||||
)
|
||||
));
|
||||
|
||||
$request = $client->get('{/path*}{?query,data*}');
|
||||
$this->assertEquals('http://test.com/foo/bar?query=hi%20there&test=a%26b', $request->getUrl());
|
||||
$this->assertEquals('hi there', $request->getQuery()->get('query'));
|
||||
$this->assertEquals('a&b', $request->getQuery()->get('test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client
|
||||
*/
|
||||
public function testQueryStringsAreNotDoubleEncodedUsingAbsolutePaths()
|
||||
{
|
||||
$client = new Client('http://test.com', array(
|
||||
'path' => array('foo', 'bar'),
|
||||
'query' => 'hi there',
|
||||
));
|
||||
$request = $client->get('http://test.com{?query}');
|
||||
$this->assertEquals('http://test.com/?query=hi%20there', $request->getUrl());
|
||||
$this->assertEquals('hi there', $request->getQuery()->get('query'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client::setUriTemplate
|
||||
* @covers Guzzle\Http\Client::getUriTemplate
|
||||
*/
|
||||
public function testAllowsUriTemplateInjection()
|
||||
{
|
||||
$client = new Client('http://test.com', array(
|
||||
'path' => array('foo', 'bar'),
|
||||
'query' => 'hi there',
|
||||
));
|
||||
|
||||
$a = $client->getUriTemplate();
|
||||
$this->assertSame($a, $client->getUriTemplate());
|
||||
$client->setUriTemplate(new UriTemplate());
|
||||
$this->assertNotSame($a, $client->getUriTemplate());
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client::expandTemplate
|
||||
*/
|
||||
public function testAllowsCustomVariablesWhenExpandingTemplates()
|
||||
{
|
||||
$client = new Client('http://test.com', array(
|
||||
'test' => 'hi',
|
||||
));
|
||||
|
||||
$uri = $client->expandTemplate('http://{test}{?query*}', array(
|
||||
'query' => array(
|
||||
'han' => 'solo'
|
||||
)
|
||||
));
|
||||
|
||||
$this->assertEquals('http://hi?han=solo', $uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client::createRequest
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testUriArrayMustContainExactlyTwoElements()
|
||||
{
|
||||
$client = new Client();
|
||||
$client->createRequest('GET', array('haha!'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client::createRequest
|
||||
* @expectedException InvalidArgumentException
|
||||
*/
|
||||
public function testUriArrayMustContainAnArray()
|
||||
{
|
||||
$client = new Client();
|
||||
$client->createRequest('GET', array('haha!', 'test'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\Client::createRequest
|
||||
* @covers Guzzle\Http\Client::get
|
||||
* @covers Guzzle\Http\Client::put
|
||||
* @covers Guzzle\Http\Client::post
|
||||
* @covers Guzzle\Http\Client::head
|
||||
* @covers Guzzle\Http\Client::options
|
||||
*/
|
||||
public function testUriArrayAllowsCustomTemplateVariables()
|
||||
{
|
||||
$client = new Client();
|
||||
$vars = array(
|
||||
'var' => 'hi'
|
||||
);
|
||||
$this->assertEquals('/hi', (string) $client->createRequest('GET', array('/{var}', $vars))->getUrl());
|
||||
$this->assertEquals('/hi', (string) $client->get(array('/{var}', $vars))->getUrl());
|
||||
$this->assertEquals('/hi', (string) $client->put(array('/{var}', $vars))->getUrl());
|
||||
$this->assertEquals('/hi', (string) $client->post(array('/{var}', $vars))->getUrl());
|
||||
$this->assertEquals('/hi', (string) $client->head(array('/{var}', $vars))->getUrl());
|
||||
$this->assertEquals('/hi', (string) $client->options(array('/{var}', $vars))->getUrl());
|
||||
}
|
||||
}
|
188
tests/Guzzle/Tests/Http/UriTemplateTest.php
Normal file
188
tests/Guzzle/Tests/Http/UriTemplateTest.php
Normal file
@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace Guzzle\Tests\Http;
|
||||
|
||||
use Guzzle\Http\UriTemplate;
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\UriTemplate
|
||||
*/
|
||||
class UriTemplateTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function templateProvider()
|
||||
{
|
||||
$t = array();
|
||||
|
||||
// Level 1 template tests
|
||||
$params = array(
|
||||
'var' => 'value',
|
||||
'hello' => 'Hello World!',
|
||||
'empty' => '',
|
||||
'path' => '/foo/bar',
|
||||
'x' => '1024',
|
||||
'y' => '768',
|
||||
'list' => array('red', 'green', 'blue'),
|
||||
'keys' => array(
|
||||
"semi" => ';',
|
||||
"dot" => '.',
|
||||
"comma" => ','
|
||||
)
|
||||
);
|
||||
|
||||
return array_map(function($t) use ($params) {
|
||||
$t[] = $params;
|
||||
return $t;
|
||||
}, array(
|
||||
array('{var}', 'value'),
|
||||
array('{hello}', 'Hello%20World%21'),
|
||||
array('{+var}', 'value'),
|
||||
array('{+hello}', 'Hello%20World!'),
|
||||
array('{+path}/here', '/foo/bar/here'),
|
||||
array('here?ref={+path}', 'here?ref=/foo/bar'),
|
||||
array('X{#var}', 'X#value'),
|
||||
array('X{#hello}', 'X#Hello%20World!'),
|
||||
array('map?{x,y}', 'map?1024,768'),
|
||||
array('{x,hello,y}', '1024,Hello%20World%21,768'),
|
||||
array('{+x,hello,y}', '1024,Hello%20World!,768'),
|
||||
array('{+path,x}/here', '/foo/bar,1024/here'),
|
||||
array('{#x,hello,y}', '#1024,Hello%20World!,768'),
|
||||
array('{#path,x}/here', '#/foo/bar,1024/here'),
|
||||
array('X{.var}', 'X.value'),
|
||||
array('X{.x,y}', 'X.1024.768'),
|
||||
array('{/var}', '/value'),
|
||||
array('{/var,x}/here', '/value/1024/here'),
|
||||
array('{;x,y}', ';x=1024;y=768'),
|
||||
array('{;x,y,empty}', ';x=1024;y=768;empty'),
|
||||
array('{?x,y}', '?x=1024&y=768'),
|
||||
array('{?x,y,empty}', '?x=1024&y=768&empty='),
|
||||
array('?fixed=yes{&x}', '?fixed=yes&x=1024'),
|
||||
array('{&x,y,empty}', '&x=1024&y=768&empty='),
|
||||
array('{var:3}', 'val'),
|
||||
array('{var:30}', 'value'),
|
||||
array('{list}', 'red,green,blue'),
|
||||
array('{list*}', 'red,green,blue'),
|
||||
array('{keys}', 'semi,%3B,dot,.,comma,%2C'),
|
||||
array('{keys*}', 'semi=%3B,dot=.,comma=%2C'),
|
||||
array('{+path:6}/here', '/foo/b/here'),
|
||||
array('{+list}', 'red,green,blue'),
|
||||
array('{+list*}', 'red,green,blue'),
|
||||
array('{+keys}', 'semi,;,dot,.,comma,,'),
|
||||
array('{+keys*}', 'semi=;,dot=.,comma=,'),
|
||||
array('{#path:6}/here', '#/foo/b/here'),
|
||||
array('{#list}', '#red,green,blue'),
|
||||
array('{#list*}', '#red,green,blue'),
|
||||
array('{#keys}', '#semi,;,dot,.,comma,,'),
|
||||
array('{#keys*}', '#semi=;,dot=.,comma=,'),
|
||||
array('X{.var:3}', 'X.val'),
|
||||
array('X{.list}', 'X.red,green,blue'),
|
||||
array('X{.list*}', 'X.red.green.blue'),
|
||||
array('X{.keys}', 'X.semi,%3B,dot,.,comma,%2C'),
|
||||
array('X{.keys*}', 'X.semi=%3B.dot=..comma=%2C'),
|
||||
array('{/var:1,var}', '/v/value'),
|
||||
array('{/list}', '/red,green,blue'),
|
||||
array('{/list*}', '/red/green/blue'),
|
||||
array('{/list*,path:4}', '/red/green/blue/%2Ffoo'),
|
||||
array('{/keys}', '/semi,%3B,dot,.,comma,%2C'),
|
||||
array('{/keys*}', '/semi=%3B/dot=./comma=%2C'),
|
||||
array('{;hello:5}', ';hello=Hello'),
|
||||
array('{;list}', ';list=red,green,blue'),
|
||||
array('{;list*}', ';list=red;list=green;list=blue'),
|
||||
array('{;keys}', ';keys=semi,%3B,dot,.,comma,%2C'),
|
||||
array('{;keys*}', ';semi=%3B;dot=.;comma=%2C'),
|
||||
array('{?var:3}', '?var=val'),
|
||||
array('{?list}', '?list=red,green,blue'),
|
||||
array('{?list*}', '?list=red&list=green&list=blue'),
|
||||
array('{?keys}', '?keys=semi,%3B,dot,.,comma,%2C'),
|
||||
array('{?keys*}', '?semi=%3B&dot=.&comma=%2C'),
|
||||
array('{&var:3}', '&var=val'),
|
||||
array('{&list}', '&list=red,green,blue'),
|
||||
array('{&list*}', '&list=red&list=green&list=blue'),
|
||||
array('{&keys}', '&keys=semi,%3B,dot,.,comma,%2C'),
|
||||
array('{&keys*}', '&semi=%3B&dot=.&comma=%2C'),
|
||||
// Test that missing expansions are skipped
|
||||
array('test{&missing*}', 'test'),
|
||||
// Test that multiple expansions can be set
|
||||
array('http://{var}/{var:2}{?keys*}', 'http://value/va?semi=%3B&dot=.&comma=%2C'),
|
||||
// Test that it is backwards compatible with {{ }} syntax
|
||||
array('{{var}}|{{var:3}}', 'value|val'),
|
||||
// Test more complex query string stuff
|
||||
array('http://www.test.com{+path}{?var,keys*}', 'http://www.test.com/foo/bar?var=value&semi=%3B&dot=.&comma=%2C')
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider templateProvider
|
||||
*/
|
||||
public function testExpandsUriTemplates($template, $expansion, $params)
|
||||
{
|
||||
$uri = new UriTemplate($template);
|
||||
$this->assertEquals($template, $uri->getTemplate());
|
||||
$result = $uri->expand($params);
|
||||
$this->assertEquals($expansion, $result);
|
||||
}
|
||||
|
||||
public function expressionProvider()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
'{+var*}', array(
|
||||
'operator' => '+',
|
||||
'values' => array(
|
||||
array('value' => 'var', 'modifier' => '*')
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
'{?keys,var,val}', array(
|
||||
'operator' => '?',
|
||||
'values' => array(
|
||||
array('value' => 'keys', 'modifier' => ''),
|
||||
array('value' => 'var', 'modifier' => ''),
|
||||
array('value' => 'val', 'modifier' => '')
|
||||
)
|
||||
),
|
||||
),
|
||||
array(
|
||||
'{+x,hello,y}', array(
|
||||
'operator' => '+',
|
||||
'values' => array(
|
||||
array('value' => 'x', 'modifier' => ''),
|
||||
array('value' => 'hello', 'modifier' => ''),
|
||||
array('value' => 'y', 'modifier' => '')
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider expressionProvider
|
||||
*/
|
||||
public function testParsesExpressions($exp, $data)
|
||||
{
|
||||
$template = new UriTemplate($exp);
|
||||
|
||||
// Access the config object
|
||||
$class = new \ReflectionClass($template);
|
||||
$method = $class->getMethod('parseExpression');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$exp = substr($exp, 1, -1);
|
||||
$this->assertEquals($data, $method->invokeArgs($template, array($exp)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers Guzzle\Http\UriTemplate::setRegex
|
||||
*/
|
||||
public function testAllowsCustomUriTemplateRegex()
|
||||
{
|
||||
$template = new UriTemplate('abc_<$var>');
|
||||
$template->setRegex('/\<\$(.+)\>/');
|
||||
$this->assertEquals('abc_hi', $template->expand(array(
|
||||
'var' => 'hi'
|
||||
)));
|
||||
}
|
||||
}
|
@ -27,16 +27,14 @@ class DynamicCommandTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
'test_command' => new ApiCommand(array(
|
||||
'doc' => 'documentationForCommand',
|
||||
'method' => 'HEAD',
|
||||
'path' => '/{{key}}',
|
||||
'uri' => '{/key}',
|
||||
'params' => array(
|
||||
'bucket' => array(
|
||||
'required' => true,
|
||||
'append' => '.',
|
||||
'location' => 'path'
|
||||
'append' => '.'
|
||||
),
|
||||
'key' => array(
|
||||
'location' => 'path',
|
||||
'prepend' => '/'
|
||||
'prepend' => 'hi_'
|
||||
),
|
||||
'acl' => array(
|
||||
'location' => 'query'
|
||||
@ -106,12 +104,12 @@ class DynamicCommandTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
$request = $command->setClient($client)->prepare();
|
||||
|
||||
// Ensure that the path values were injected into the path and base_url
|
||||
$this->assertEquals('/key', $request->getPath());
|
||||
$this->assertEquals('/hi_key', $request->getPath());
|
||||
$this->assertEquals('www.example.com', $request->getHost());
|
||||
|
||||
// Check the complete request
|
||||
$this->assertEquals(
|
||||
"HEAD /key HTTP/1.1\r\n" .
|
||||
"HEAD /hi_key HTTP/1.1\r\n" .
|
||||
"Host: www.example.com\r\n" .
|
||||
"User-Agent: " . Guzzle::getDefaultUserAgent() . "\r\n" .
|
||||
"\r\n", (string) $request);
|
||||
|
@ -35,7 +35,7 @@ class ApiCommandTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
$this->assertEquals('test', $c->getName());
|
||||
$this->assertEquals('doc', $c->getDoc());
|
||||
$this->assertEquals('POST', $c->getMethod());
|
||||
$this->assertEquals('/api/v1', $c->getPath());
|
||||
$this->assertEquals('/api/v1', $c->getUri());
|
||||
$this->assertEquals('Guzzle\\Service\\Command\\DynamicCommand', $c->getConcreteClass());
|
||||
$this->assertEquals(array(
|
||||
'key' => new Collection(array(
|
||||
@ -86,7 +86,7 @@ class ApiCommandTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
'class' => 'Guzzle\\Service\\Command\ClosureCommand',
|
||||
'doc' => 'test',
|
||||
'method' => 'PUT',
|
||||
'path' => '/',
|
||||
'uri' => '/',
|
||||
'params' => array(
|
||||
'p' => new Collection(array(
|
||||
'name' => 'foo'
|
||||
|
@ -22,8 +22,8 @@ class JsonDescriptionBuilderTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
$description = JsonDescriptionBuilder::build(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'TestData' . DIRECTORY_SEPARATOR . 'test_service.json');
|
||||
$this->assertTrue($description->hasCommand('test'));
|
||||
$test = $description->getCommand('test');
|
||||
$this->assertEquals('/path', $test->getPath());
|
||||
$this->assertEquals('/path', $test->getUri());
|
||||
$test = $description->getCommand('concrete');
|
||||
$this->assertEquals('/abstract', $test->getPath());
|
||||
$this->assertEquals('/abstract', $test->getUri());
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ class ServiceDescriptionTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
));
|
||||
|
||||
$c = $d->getCommand('concrete');
|
||||
$this->assertEquals('/test', $c->getPath());
|
||||
$this->assertEquals('/test', $c->getUri());
|
||||
$this->assertEquals('GET', $c->getMethod());
|
||||
$params = $c->getParams();
|
||||
$param = $params['test'];
|
||||
|
@ -46,7 +46,7 @@ class XmlDescriptionBuilderTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
), $command->getParam('bucket')->getAll());
|
||||
|
||||
$this->assertEquals('DELETE', $command->getMethod());
|
||||
$this->assertEquals('{{ bucket }}/{{ key }}{{ format }}', $command->getPath());
|
||||
$this->assertEquals('{{ bucket }}/{{ key }}{{ format }}', $command->getUri());
|
||||
$this->assertEquals('Documentation', $command->getDoc());
|
||||
|
||||
$this->assertArrayHasKey('custom_filter', Inspector::getInstance()->getRegisteredConstraints());
|
||||
@ -59,6 +59,6 @@ class XmlDescriptionBuilderTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
{
|
||||
$service = XmlDescriptionBuilder::build(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'TestData' . DIRECTORY_SEPARATOR . 'test_service.xml');
|
||||
$command = $service->getCommand('concrete');
|
||||
$this->assertEquals('/test', $command->getPath());
|
||||
$this->assertEquals('/test', $command->getUri());
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
<!-- Add commands to the service -->
|
||||
<commands>
|
||||
|
||||
<command name="test" method="DELETE" path="{{ bucket }}/{{ key }}{{ format }}" min_args="2">
|
||||
<command name="test" method="DELETE" uri="{{ bucket }}/{{ key }}{{ format }}" min_args="2">
|
||||
<doc>Documentation</doc>
|
||||
<param name="format" required="false" default="json" type="choice:json,xml" location="path" prepend="." />
|
||||
<param name="bucket" required="true" location="path" doc="Bucket location" />
|
||||
@ -36,18 +36,18 @@
|
||||
<param name="result_type" type="string" required="false"/>
|
||||
</command>
|
||||
|
||||
<command name="trends.location" method="GET" min_args="1" path="/trends/{{ woeid }}">
|
||||
<command name="trends.location" method="GET" min_args="1" uri="/trends/{{ woeid }}">
|
||||
<param name="woeid" type="integer" required="true" location="path" />
|
||||
<param name="acl" required="true" location="header:X-Amz-Acl" />
|
||||
</command>
|
||||
|
||||
<command name="geo.id" method="GET" auth_required="true" path="/geo/id/{{ place_id }}">
|
||||
<command name="geo.id" method="GET" auth_required="true" uri="/geo/id/{{ place_id }}">
|
||||
<param name="place_id" type="string" required="true" prepend="/" append=".id" />
|
||||
<!-- The request builder will remove '//', so it's okay to always prepend / if needed -->
|
||||
<param name="second" type="string" required="true" prepend="/" />
|
||||
</command>
|
||||
|
||||
<command name="path" method="GET" path="/test" />
|
||||
<command name="path" method="GET" uri="/test" />
|
||||
|
||||
<command name="concrete" extends="abstract" />
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user