我有一个使用HTTPS协议的整个网站。但最近我注意到很奇怪的Yii bahaviour。当我进行重定向时:
$this->redirect('/article/123456');
它首先302重定向到 http 版本的页面(我可以通过标题看到):
HTTP://site.xyz/article/123456
X-Powered-By:PHP / 5.4.45-0 + deb7u2
然后NGINX执行301重定向到 https 版本:
HTTPS://site.xyz/article/123456
为什么会发生这种情况?Yii如何构建一个绝对URL(总是认为它使用相对的URL)?
答案 0 :(得分:2)
/**
* Redirects the browser to the specified URL.
* @param string $url URL to be redirected to. Note that when URL is not
* absolute (not starting with "/") it will be relative to current request URL.
* @param boolean $terminate whether to terminate the current application
* @param integer $statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html}
* for details about HTTP status code.
*/
public function redirect($url,$terminate=true,$statusCode=302)
{
if(strpos($url,'/')===0 && strpos($url,'//')!==0)
$url=$this->getHostInfo().$url;
header('Location: '.$url, true, $statusCode);
if($terminate)
Yii::app()->end();
}
检查有关URL参数的说明:
@param string $ url要重定向到的URL。 请注意,当URL不是时 *绝对(不以“/”开头)它将与当前请求URL相关。
但是,在您的代码中,URL以“/”开头,因此根据源代码,接下来会发生的事情是:$ url = $ this-> getHostInfo()。$ url;
那么让我们来看看getHostInfo函数的来源:
public function getHostInfo($schema='')
{
if($this->_hostInfo===null)
{
if($secure=$this->getIsSecureConnection())
$http='https';
else
$http='http';
if(isset($_SERVER['HTTP_HOST']))
$this->_hostInfo=$http.'://'.$_SERVER['HTTP_HOST'];
else
{
$this->_hostInfo=$http.'://'.$_SERVER['SERVER_NAME'];
$port=$secure ? $this->getSecurePort() : $this->getPort();
if(($port!==80 && !$secure) || ($port!==443 && $secure))
$this->_hostInfo.=':'.$port;
}
}
if($schema!=='')
{
$secure=$this->getIsSecureConnection();
if($secure && $schema==='https' || !$secure && $schema==='http')
return $this->_hostInfo;
$port=$schema==='https' ? $this->getSecurePort() : $this->getPort();
if($port!==80 && $schema==='http' || $port!==443 && $schema==='https')
$port=':'.$port;
else
$port='';
$pos=strpos($this->_hostInfo,':');
return $schema.substr($this->_hostInfo,$pos,strcspn($this->_hostInfo,':',$pos+1)+1).$port;
}
else
return $this->_hostInfo;
}
我建议你检查第一个条件是否返回true(虽然我发现很可能没有定义_hostInfo)并检查$ this-> getIsSecureConnection()函数的结果。