mirror of
https://github.com/guzzle/guzzle.git
synced 2025-02-24 18:13:00 +01:00
Properly merging URLs and removing dot segments based on RFC 3986 section 5.4. Closes #288 and #289.
This commit is contained in:
parent
6290b06491
commit
cdb1da7d1a
@ -285,28 +285,32 @@ class Url
|
||||
// Replace // and /./ with /
|
||||
$this->path = str_replace(array('/./', '//'), '/', $this->path);
|
||||
|
||||
// Remove trailing relative paths if possible
|
||||
$segments = $this->getPathSegments();
|
||||
$last = end($segments);
|
||||
$trailingSlash = false;
|
||||
if ($last === '') {
|
||||
array_pop($segments);
|
||||
$trailingSlash = true;
|
||||
}
|
||||
// Remove dot segments
|
||||
if (strpos($this->path, '..') !== false) {
|
||||
|
||||
while ($last == '..' || $last == '.') {
|
||||
if ($last == '..') {
|
||||
// Remove trailing relative paths if possible
|
||||
$segments = $this->getPathSegments();
|
||||
$last = end($segments);
|
||||
$trailingSlash = false;
|
||||
if ($last === '') {
|
||||
array_pop($segments);
|
||||
$last = array_pop($segments);
|
||||
$trailingSlash = true;
|
||||
}
|
||||
if ($last == '.' || $last == '') {
|
||||
$last = array_pop($segments);
|
||||
}
|
||||
}
|
||||
|
||||
$this->path = implode('/', $segments);
|
||||
if ($trailingSlash) {
|
||||
$this->path .= '/';
|
||||
while ($last == '..' || $last == '.') {
|
||||
if ($last == '..') {
|
||||
array_pop($segments);
|
||||
$last = array_pop($segments);
|
||||
}
|
||||
if ($last == '.' || $last == '') {
|
||||
$last = array_pop($segments);
|
||||
}
|
||||
}
|
||||
|
||||
$this->path = implode('/', $segments);
|
||||
if ($trailingSlash) {
|
||||
$this->path .= '/';
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
@ -468,60 +472,66 @@ class Url
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the URL with another URL. Parts specified in the passed URL will supersede parts in the current URL.
|
||||
* Combine the URL with another URL. Follows the rules specific in RFC 3986 section 5.4.
|
||||
*
|
||||
* @param string $url Relative URL to combine with
|
||||
*
|
||||
* @return Url
|
||||
* @throws InvalidArgumentException
|
||||
* @link http://tools.ietf.org/html/rfc3986#section-5.4
|
||||
*/
|
||||
public function combine($url)
|
||||
{
|
||||
$absolutePath = $url[0] == '/';
|
||||
$url = self::factory($url);
|
||||
|
||||
// Use the more absolute URL as the base URL
|
||||
if (!$this->isAbsolute() && $url->isAbsolute()) {
|
||||
$url = $url->combine($this);
|
||||
}
|
||||
|
||||
// Passing a URL with a scheme overrides everything
|
||||
if ($buffer = $url->getScheme()) {
|
||||
$this->scheme = $buffer;
|
||||
$this->host = $url->getHost();
|
||||
$this->port = $url->getPort();
|
||||
$this->username = $url->getUsername();
|
||||
$this->password = $url->getPassword();
|
||||
$this->path = $url->getPath();
|
||||
$this->query = $url->getQuery();
|
||||
$this->fragment = $url->getFragment();
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Setting a host overrides the entire rest of the URL
|
||||
if ($buffer = $url->getHost()) {
|
||||
$this->host = $buffer;
|
||||
$this->port = $url->getPort();
|
||||
$this->username = $url->getUsername();
|
||||
$this->password = $url->getPassword();
|
||||
$this->path = $url->getPath();
|
||||
$this->fragment = $url->getFragment();
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($buffer = $url->getPort()) {
|
||||
$this->port = $buffer;
|
||||
}
|
||||
$path = $url->getPath();
|
||||
$query = $url->getQuery();
|
||||
|
||||
if ($buffer = $url->getUsername()) {
|
||||
$this->username = $buffer;
|
||||
}
|
||||
|
||||
if ($buffer = $url->getPassword()) {
|
||||
$this->password = $buffer;
|
||||
}
|
||||
|
||||
if ($buffer = $url->getFragment()) {
|
||||
$this->fragment = $buffer;
|
||||
}
|
||||
|
||||
if ($absolutePath) {
|
||||
// Replace the current URL and query if set
|
||||
if ($buffer = $url->getPath()) {
|
||||
$this->path = $buffer;
|
||||
}
|
||||
if (count($url->getQuery())) {
|
||||
$this->query = $url->getQuery();
|
||||
if (!$path) {
|
||||
if (count($query)) {
|
||||
$this->query = $query;
|
||||
}
|
||||
} else {
|
||||
// Append to the current path and query string
|
||||
if ($buffer = $url->getPath()) {
|
||||
$this->addPath($buffer);
|
||||
}
|
||||
if ($buffer = $url->getQuery()) {
|
||||
$this->query->merge($buffer);
|
||||
if ($path[0] == '/') {
|
||||
$this->path = $path;
|
||||
} else {
|
||||
$this->path .= '/' . $path;
|
||||
}
|
||||
$this->normalizePath();
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
$this->fragment = $url->getFragment();
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
@ -304,8 +304,8 @@ class ClientTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
array($u, '/absolute/path/to/resource', $this->getServer()->getUrl() . 'absolute/path/to/resource'),
|
||||
array($u, '/absolute/path/to/resource?a=b&c=d', $this->getServer()->getUrl() . 'absolute/path/to/resource?a=b&c=d'),
|
||||
array($u2, '/absolute/path/to/resource?a=b&c=d', $this->getServer()->getUrl() . 'absolute/path/to/resource?a=b&c=d'),
|
||||
array($u2, 'relative/path/to/resource', $this->getServer()->getUrl() . 'base/relative/path/to/resource?z=1'),
|
||||
array($u2, 'relative/path/to/resource?another=query', $this->getServer()->getUrl() . 'base/relative/path/to/resource?z=1&another=query')
|
||||
array($u2, 'relative/path/to/resource', $this->getServer()->getUrl() . 'base/relative/path/to/resource'),
|
||||
array($u2, 'relative/path/to/resource?another=query', $this->getServer()->getUrl() . 'base/relative/path/to/resource?another=query')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -148,12 +148,13 @@ class UrlTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
array('http://www.example.com/path', 'more', 'http://www.example.com/path/more'),
|
||||
array('http://www.example.com/path', 'more?q=1', 'http://www.example.com/path/more?q=1'),
|
||||
array('http://www.example.com/', '?q=1', 'http://www.example.com/?q=1'),
|
||||
array('http://www.example.com/path', 'http://test.com', 'http://test.com/path'),
|
||||
array('http://www.example.com:8080/path', 'http://test.com', 'http://test.com/path'),
|
||||
array('http://www.example.com/path', 'http://test.com', 'http://test.com'),
|
||||
array('http://www.example.com:8080/path', 'http://test.com', 'http://test.com'),
|
||||
array('http://www.example.com:8080/path', '?q=2#abc', 'http://www.example.com:8080/path?q=2#abc'),
|
||||
array('http://u:a@www.example.com/path', 'test', 'http://u:a@www.example.com/path/test'),
|
||||
array('http://www.example.com/path', 'http://u:a@www.example.com/', 'http://u:a@www.example.com/path'),
|
||||
array('http://www.example.com/path', 'http://u:a@www.example.com/', 'http://u:a@www.example.com/'),
|
||||
array('/path?q=2', 'http://www.test.com/', 'http://www.test.com/path?q=2'),
|
||||
array('http://api.flickr.com/services/', 'http://www.flickr.com/services/oauth/access_token', 'http://www.flickr.com/services/oauth/access_token')
|
||||
);
|
||||
}
|
||||
|
||||
@ -198,10 +199,11 @@ class UrlTest extends \Guzzle\Tests\GuzzleTestCase
|
||||
array('/foo/../..', ''),
|
||||
array('/foo/../.', ''),
|
||||
array('/./foo/..', ''),
|
||||
array('/./foo', 'foo'),
|
||||
array('/./foo/', 'foo/'),
|
||||
array('/./foo', '/foo'),
|
||||
array('/./foo/', '/foo/'),
|
||||
array('/./foo/bar/baz/pho/../..', 'foo/bar'),
|
||||
array('*', '*')
|
||||
array('*', '*'),
|
||||
array('/foo', '/foo')
|
||||
);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user