Commit 1c3e61ec by Qiang Xue

Fixes #4591: `yii\helpers\Url::to()` will no longer prefix relative URLs with the base URL

parent 0cfaa17b
...@@ -216,6 +216,7 @@ Yii Framework 2 Change Log ...@@ -216,6 +216,7 @@ Yii Framework 2 Change Log
- Chg #4310: Removed `$data` from signature of `yii\rbac\ManagerInterface` (samdark) - Chg #4310: Removed `$data` from signature of `yii\rbac\ManagerInterface` (samdark)
- Chg #4318: `yii\helpers\Html::ul()` and `ol()` will return an empty list tag if an empty item array is given (qiangxue) - Chg #4318: `yii\helpers\Html::ul()` and `ol()` will return an empty list tag if an empty item array is given (qiangxue)
- Chg #4331: `yii\helpers\Url` now uses `UrlManager` to determine base URL when generating URLs (qiangxue) - Chg #4331: `yii\helpers\Url` now uses `UrlManager` to determine base URL when generating URLs (qiangxue)
- Chg #4591: `yii\helpers\Url::to()` will no longer prefix relative URLs with the base URL (qiangxue)
- Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue) - Chg: Replaced `clearAll()` and `clearAllAssignments()` in `yii\rbac\ManagerInterface` with `removeAll()`, `removeAllRoles()`, `removeAllPermissions()`, `removeAllRules()` and `removeAllAssignments()` (qiangxue)
- Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue) - Chg: Added `$user` as the first parameter of `yii\rbac\Rule::execute()` (qiangxue)
- Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe) - Chg: `yii\grid\DataColumn::getDataCellValue()` visibility is now `public` to allow accessing the value from a GridView directly (cebe)
......
...@@ -174,6 +174,10 @@ new ones save the following code as `convert.php` that should be placed in the s ...@@ -174,6 +174,10 @@ new ones save the following code as `convert.php` that should be placed in the s
``` ```
* Due to significant changes to security you need to upgrade your code to use `\yii\base\Security` component instead of * Due to significant changes to security you need to upgrade your code to use `\yii\base\Security` component instead of
helper. If you have any data encrypted it should be re-encrypted. In order to do so you can use old security helper [as helper. If you have any data encrypted it should be re-encrypted. In order to do so you can use old security helper
explained by @docsolver at github](https://github.com/yiisoft/yii2/issues/4461#issuecomment-50237807). [as explained by @docsolver at github](https://github.com/yiisoft/yii2/issues/4461#issuecomment-50237807).
* [[yii\helpers\Url::to()]] will no longer prefix base URL to relative URLs. For example, `Url::to('images/logo.png')`
will return `images/logo.png` directly. If you want a relative URL to be prefix with base URL, you should make use
of the alias `@web`. For example, `Url::to('@web/images/logo.png')` will return `/BaseUrl/images/logo.png`.
...@@ -73,7 +73,7 @@ class BaseUrl ...@@ -73,7 +73,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the generated URL: * @param boolean|string $scheme the URI scheme to use in the generated URL:
* *
* - `false` (default): generating a relative URL. * - `false` (default): generating a relative URL.
* - `true`: generating an absolute URL whose scheme is the same as the current request. * - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: generating an absolute URL with the specified scheme (either `http` or `https`). * - string: generating an absolute URL with the specified scheme (either `http` or `https`).
* *
* @return string the generated URL * @return string the generated URL
...@@ -133,21 +133,20 @@ class BaseUrl ...@@ -133,21 +133,20 @@ class BaseUrl
* Creates a URL based on the given parameters. * Creates a URL based on the given parameters.
* *
* This method is very similar to [[toRoute()]]. The only difference is that this method * This method is very similar to [[toRoute()]]. The only difference is that this method
* requires a route to be specified as an array only. If a string is given, it will be treated * requires a route to be specified as an array only. If a string is given, it will be treated as a URL.
* as a URL which will be prefixed with the base URL if it does not start with a slash.
* In particular, if `$url` is * In particular, if `$url` is
* *
* - an array: [[toRoute()]] will be called to generate the URL. For example: * - an array: [[toRoute()]] will be called to generate the URL. For example:
* `['site/index']`, `['post/index', 'page' => 2]`. Please refer to [[toRoute()]] for more details * `['site/index']`, `['post/index', 'page' => 2]`. Please refer to [[toRoute()]] for more details
* on how to specify a route. * on how to specify a route.
* - a string with a leading `@`: it is treated as an alias and the corresponding aliased string * - a string with a leading `@`: it is treated as an alias, and the corresponding aliased string
* will be subject to the following rules. * will be returned.
* - an empty string: the currently requested URL will be returned; * - an empty string: the currently requested URL will be returned;
* - a string without a leading slash: it will be prefixed with [[\yii\web\Request::baseUrl]]. * - a normal string: it will be returned as is.
* - a string with a leading slash: it will be returned as is.
* *
* Note that in case `$scheme` is specified (either a string or true), an absolute URL with host info * When `$scheme` is specified (either a string or true), an absolute URL with host info (obtained from
* will be returned. * [[\yii\web\UrlManager::hostInfo]]) will be returned. If `$url` is already an absolute URL, its scheme
* will be replaced with the specified one.
* *
* Below are some examples of using this method: * Below are some examples of using this method:
* *
...@@ -162,13 +161,16 @@ class BaseUrl ...@@ -162,13 +161,16 @@ class BaseUrl
* echo Url::to(); * echo Url::to();
* *
* // /images/logo.gif * // /images/logo.gif
* echo Url::to('@web/images/logo.gif');
*
* // images/logo.gif
* echo Url::to('images/logo.gif'); * echo Url::to('images/logo.gif');
* *
* // http://www.example.com/index.php?r=site/index * // http://www.example.com/images/logo.gif
* echo Url::to(['site/index'], true); * echo Url::to('@web/images/logo.gif', true);
* *
* // https://www.example.com/index.php?r=site/index * // https://www.example.com/images/logo.gif
* echo Url::to(['site/index'], 'https'); * echo Url::to('@web/images/logo.gif', 'https');
* ``` * ```
* *
* *
...@@ -176,7 +178,7 @@ class BaseUrl ...@@ -176,7 +178,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the generated URL: * @param boolean|string $scheme the URI scheme to use in the generated URL:
* *
* - `false` (default): generating a relative URL. * - `false` (default): generating a relative URL.
* - `true`: generating an absolute URL whose scheme is the same as the current request. * - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: generating an absolute URL with the specified scheme (either `http` or `https`). * - string: generating an absolute URL with the specified scheme (either `http` or `https`).
* *
* @return string the generated URL * @return string the generated URL
...@@ -188,25 +190,28 @@ class BaseUrl ...@@ -188,25 +190,28 @@ class BaseUrl
return static::toRoute($url, $scheme); return static::toRoute($url, $scheme);
} }
$url = (string) Yii::getAlias($url); $url = Yii::getAlias($url);
if ($url === '') { if ($url === '') {
$url = Yii::$app->getRequest()->getUrl(); $url = Yii::$app->getRequest()->getUrl();
} else {
$hasScheme = ($pos = strpos($url, ':')) > 0 && ctype_alpha(substr($url, 0, $pos));
$char = $url[0];
if ($char !== '/' && $char !== '#' && $char !== '.' && !$hasScheme) {
$url = Yii::$app->getUrlManager()->getBaseUrl() . '/' . $url;
}
} }
if ($scheme) { if (!$scheme) {
if (empty($hasScheme)) { return $url;
$url = Yii::$app->getUrlManager()->getHostInfo() . '/' . ltrim($url, '/'); }
}
if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) { if (strncmp($url, '//', 2) === 0) {
$url = $scheme . substr($url, $pos); // e.g. //hostname/path/to/resource
} return is_string($scheme) ? "$scheme:$url" : $url;
}
if (($pos = strpos($url, ':')) == false || !ctype_alpha(substr($url, 0, $pos))) {
// turn relative URL into absolute
$url = Yii::$app->getUrlManager()->getHostInfo() . '/' . ltrim($url, '/');
}
if (is_string($scheme) && ($pos = strpos($url, ':')) !== false) {
// replace the scheme with the specified one
$url = $scheme . substr($url, $pos);
} }
return $url; return $url;
...@@ -217,7 +222,7 @@ class BaseUrl ...@@ -217,7 +222,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use in the returned base URL: * @param boolean|string $scheme the URI scheme to use in the returned base URL:
* *
* - `false` (default): returning the base URL without host info. * - `false` (default): returning the base URL without host info.
* - `true`: returning an absolute base URL whose scheme is the same as the current request. * - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: returning an absolute base URL with the specified scheme (either `http` or `https`). * - string: returning an absolute base URL with the specified scheme (either `http` or `https`).
* @return string * @return string
*/ */
...@@ -296,7 +301,7 @@ class BaseUrl ...@@ -296,7 +301,7 @@ class BaseUrl
* @param boolean|string $scheme the URI scheme to use for the returned URL: * @param boolean|string $scheme the URI scheme to use for the returned URL:
* *
* - `false` (default): returning a relative URL. * - `false` (default): returning a relative URL.
* - `true`: returning an absolute URL whose scheme is the same as the current request. * - `true`: returning an absolute base URL whose scheme is the same as that in [[\yii\web\UrlManager::hostInfo]].
* - string: returning an absolute URL with the specified scheme (either `http` or `https`). * - string: returning an absolute URL with the specified scheme (either `http` or `https`).
* *
* @return string home URL * @return string home URL
......
...@@ -121,21 +121,22 @@ class UrlTest extends TestCase ...@@ -121,21 +121,22 @@ class UrlTest extends TestCase
\Yii::setAlias('@web4', '/test'); \Yii::setAlias('@web4', '/test');
\Yii::setAlias('@web5', '#test'); \Yii::setAlias('@web5', '#test');
$this->assertEquals('/base/test/me1', Url::to('test/me1')); $this->assertEquals('test/me1', Url::to('test/me1'));
$this->assertEquals('javascript:test/me1', Url::to('javascript:test/me1')); $this->assertEquals('javascript:test/me1', Url::to('javascript:test/me1'));
$this->assertEquals('/base/java/script:test/me1', Url::to('java/script:test/me1')); $this->assertEquals('java/script:test/me1', Url::to('java/script:test/me1'));
$this->assertEquals('#test/me1', Url::to('#test/me1')); $this->assertEquals('#test/me1', Url::to('#test/me1'));
$this->assertEquals('.test/me1', Url::to('.test/me1')); $this->assertEquals('.test/me1', Url::to('.test/me1'));
$this->assertEquals('http://example.com/base/test/me1', Url::to('test/me1', true)); $this->assertEquals('http://example.com/test/me1', Url::to('test/me1', true));
$this->assertEquals('https://example.com/base/test/me1', Url::to('test/me1', 'https')); $this->assertEquals('https://example.com/test/me1', Url::to('test/me1', 'https'));
$this->assertEquals('https://example.com/test/test/me1', Url::to('@web4/test/me1', 'https'));
$this->assertEquals('http://test.example.com/test/me1', Url::to('@web1')); $this->assertEquals('http://test.example.com/test/me1', Url::to('@web1'));
$this->assertEquals('http://test.example.com/test/me1', Url::to('@web1', true)); $this->assertEquals('http://test.example.com/test/me1', Url::to('@web1', true));
$this->assertEquals('https://test.example.com/test/me1', Url::to('@web1', 'https')); $this->assertEquals('https://test.example.com/test/me1', Url::to('@web1', 'https'));
$this->assertEquals('/base/test/me2', Url::to('@web2')); $this->assertEquals('test/me2', Url::to('@web2'));
$this->assertEquals('http://example.com/base/test/me2', Url::to('@web2', true)); $this->assertEquals('http://example.com/test/me2', Url::to('@web2', true));
$this->assertEquals('https://example.com/base/test/me2', Url::to('@web2', 'https')); $this->assertEquals('https://example.com/test/me2', Url::to('@web2', 'https'));
$this->assertEquals('/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3')); $this->assertEquals('/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3'));
$this->assertEquals('http://example.com/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3', true)); $this->assertEquals('http://example.com/base/index.php&r=site%2Fcurrent&id=42', Url::to('@web3', true));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment