Yii:奇怪的重定向行为(https - > http)

时间:2017-02-07 14:07:04

标签: php yii

我有一个使用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)?

1 个答案:

答案 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();
    }

Source

检查有关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()函数的结果。