Zend Hostname Router 和 url helper:丢失端口

发布于 2024-08-21 04:06:53 字数 1147 浏览 9 评论 0原文

我想保留在生产和开发环境中不同的端口号,但是基于我的 zend 路由调用 url 帮助器会忘记端口号。

我的路由是一堆正则表达式路由,与默认主机名路由链接,主要用于多域配置上的多语言(下面简短概述)。

<?php
    $routecateg = new Zend_Controller_Router_Route_Regex('cat/(\w+)_([^_]+)(?:_page_(\d+))?(?:_par_(\d+))?(?:.html)?',
    array(1 =>'',2=>'',3=>'1',4=>'20','controller' =>'list','action'=>'categ'),
    array(1 =>'categid',2=>'categname',3=>'page',4=>'par'),
    'cat/%s_%s_page_%d_par_%d.html'
);

$routeindex= new Zend_Controller_Router_Route_Regex('(index|home)?',
    array('controller' =>'index','action'=>'home'),
    array(),
    'index'
);    

$hostRouteRepository = new Zend_Controller_Router_Route_Hostname(
    ':lang.'.$config->serverurl
);
$router ->addRoute('index',$hostRouteRepository->chain($routeindex));
$router ->addRoute('categ',$hostRouteRepository->chain($routecateg));
?>

其中 $config->serverurl 只是域名,具体取决于环境并在我的 application.ini 文件中配置。

在我的生产服务器上,没问题,因为我在默认端口 80 上运行,但在developmenet上,我需要在不同的端口上运行,每次我调用我的 url 帮助程序时,端口号被遗忘

我知道我可以通过更好地配置我的 apache 服务器来解决此问题,但我很惊讶没有找到此问题的任何解决方案。

I would like to keep my port number which is different on production and development environment, but calls to the url helper based on my zend routes forget the port number.

My routes are a bunch of regexp routes, chaining with default hostname routes, mainly for multilanguage over a multidomain configuration (short overview below).

<?php
    $routecateg = new Zend_Controller_Router_Route_Regex('cat/(\w+)_([^_]+)(?:_page_(\d+))?(?:_par_(\d+))?(?:.html)?',
    array(1 =>'',2=>'',3=>'1',4=>'20','controller' =>'list','action'=>'categ'),
    array(1 =>'categid',2=>'categname',3=>'page',4=>'par'),
    'cat/%s_%s_page_%d_par_%d.html'
);

$routeindex= new Zend_Controller_Router_Route_Regex('(index|home)?',
    array('controller' =>'index','action'=>'home'),
    array(),
    'index'
);    

$hostRouteRepository = new Zend_Controller_Router_Route_Hostname(
    ':lang.'.$config->serverurl
);
$router ->addRoute('index',$hostRouteRepository->chain($routeindex));
$router ->addRoute('categ',$hostRouteRepository->chain($routecateg));
?>

Where $config->serverurl is just the domainname depending on environment and configured in my application.ini file.

On my production server, it's ok, as i am running on default port 80, but on developmenet, I need to run on a different port, and each time i call my url helper, port number is forgotten.

I know i can workaround by better configuring my apache server, but i'm surprised to not find any solutions to this issue.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夢归不見 2024-08-28 04:06:53

这是我发现的:

如果您将诸如 ':lang.example.com:8888' 或 ':lang.example.com:port' 之类的内容传递给 Zend_Controller_Router_Route_Hostname 的构造函数,则端口部分将不会被正确解析(com: 8888 或 com:端口)。这是因为字符串被“.”分解了。字符,并且仅在构造中分解部分的第一个字符上检查主机变量字符(':'):

foreach (explode('.', $route) as $pos => $part) {
            if (substr($part, 0, 1) == $this->_hostVariable) {
                $name = substr($part, 1);
                $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name]
                                       : $this->_defaultRegex);
                $this->_variables[$pos] = $name;
            } else {
                $this->_parts[$pos] = $part;
                $this->_staticCount++;
            }
        }

现在,在路由匹配函数(函数match($ request))中,端口号从请求中被丢弃将阻止匹配路由的有效请求:

// Get the host and remove unnecessary port information
    $host = $request->getHttpHost();
    if (preg_match('#:\d+$#', $host, $result) === 1) {
        $host = substr($host, 0, -strlen($result[0]));
    }

我相信有 3 种不同的方法可以解决您的问题:

  1. 在 config.ini 文件中添加端口号选项并将其注册到 Zend_Registry,如下所示:
    Zend_Registry::set('PORT_NUMBER', $this->getOption('portnumber'));
  2. 修复函数 match($request) 中的代码以保留端口号(注释掉该代码)上面显示的应该可以做到这一点)
  3. 修复构造函数中的代码以允许路由的“:port”参数化(您可能希望在设置路由时使用必需或默认值)

注意:解决方案 2 似乎比 3 更容易,但是需要一些额外的工作,因为端口号将由 assemble 函数进行 urlencoded:

foreach (array_reverse($host, true) as $key => $value) {
        if ($flag || !isset($this->_variables[$key]) || $value !== $this->getDefault($this->_variables[$key]) || $partial) {
            if ($encode) $value = urlencode($value);
            $return = '.' . $value . $return;

            $flag = true;
        }
    }

解决方案 3 不应该发生这种情况,因为端口号是一个变量。

希望有帮助。

Here is what I found:

If you pass something like ':lang.example.com:8888' or ':lang.example.com:port' to the constructor of Zend_Controller_Router_Route_Hostname, the port part won't be correctly parsed (com:8888 or com:port). This is due to the fact that the string is exploded with the '.' character and that the hostVariable character (':') is only checked on the first character of the exploded parts in construct:

foreach (explode('.', $route) as $pos => $part) {
            if (substr($part, 0, 1) == $this->_hostVariable) {
                $name = substr($part, 1);
                $this->_parts[$pos] = (isset($reqs[$name]) ? $reqs[$name]
                                       : $this->_defaultRegex);
                $this->_variables[$pos] = $name;
            } else {
                $this->_parts[$pos] = $part;
                $this->_staticCount++;
            }
        }

Now, in the route matching function (function match($request)), the port number is discarded from the request which will prevent valid requests to match the route:

// Get the host and remove unnecessary port information
    $host = $request->getHttpHost();
    if (preg_match('#:\d+$#', $host, $result) === 1) {
        $host = substr($host, 0, -strlen($result[0]));
    }

I believe that there are 3 different ways to solve your problem:

  1. Add a port number option in your config.ini file and register it to the Zend_Registry with something like:
    Zend_Registry::set('PORT_NUMBER', $this->getOption('portnumber'));
  2. Fix the code in the function match($request) to keep the port number (commenting out the code shown above should do it)
  3. Fix the code in the constructor to allow for ':port' parametrization of the route (you might want to use a required or a default value when setting up your route)

Note: solution 2 seems easier than 3 but some additional work is needed because the port number will be urlencoded by the assemble function:

foreach (array_reverse($host, true) as $key => $value) {
        if ($flag || !isset($this->_variables[$key]) || $value !== $this->getDefault($this->_variables[$key]) || $partial) {
            if ($encode) $value = urlencode($value);
            $return = '.' . $value . $return;

            $flag = true;
        }
    }

This should not happen with solution 3 because the port number is a variable.

Hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文