【问题标题】:How to replace special character in HTTP request URI?如何替换 HTTP 请求 URI 中的特殊字符?
【发布时间】:2013-06-19 14:10:36
【问题描述】:

在基于 Zend Framework 2 的网站上(nginx 上的测试环境和 Apache 上的实时环境)有一个类别“课程”,其页面具有如下 URI:

domain.tld/courses/123-Name of course that can contain ®, €, (, ), and other special chars

课程名称来自数据库,并为内部链接进行 URL 编码:

domain.tld/courses/123-Name%20of%20course%20that%20can%20contain%20%C2%AE%2C%20%E2%82%AC%2C%20%C3%A4%2C%20(%2C%20)%2C%20and%20other%20special%20chars

它工作正常,但是当我尝试使用不编码的特殊字符访问页面时发生 404 错误。

使用空格字符的网站示例是维基百科。你可以使用

http://en.wikipedia.org/wiki/Signal_(electrical_engineering)

http://en.wikipedia.org/wiki/Signal_%28electrical_engineering%29

并且总是得到你想要的页面。

有人知道如何实现这种行为(“à la Wikipedia”)吗? (也许使用 .htaccess 规则进行 HTTP 重定向?)


更新:

/etc/nginx/ax-common-vhost

server {
    listen   80;
    server_name
        foo.loc
        bar.loc
        baz.loc
    ;

    if ($host ~ ^(?<project>.+)\.(?<area>.+)\.loc$) {
        set $folder "$area/$project";
    }

    access_log /var/log/nginx/$area/$project.access.log;
    error_log /var/log/nginx/error.log;

    gzip on;
    gzip_min_length 1000;
    gzip_types text/plain text/xml application/xml;

    client_max_body_size 25m;

    root /var/www/$folder/public/;

    try_files $uri $uri/ /index.php?$args;
    index index.html index.php;

    location / {
        index index.html index.php;
    sendfile off;
    }

    location ~ (\.inc\.php|\.tpl|\.sql|\.tpl\.php|\.db)$ {
        deny all;
    }

    location ~ \.htaccess {
        deny all;
    }

    if (!-e $request_filename) {
        rewrite ^.*$ /index.php last;
    }

    location ~ \.php$ {
      fastcgi_cache        off;
      #fastcgi_pass        127.0.0.1:9001;
      fastcgi_pass         unix:/var/run/php5-fpm.sock;
      fastcgi_read_timeout 6000;
      fastcgi_index        index.php;
      include              fastcgi_params;
      fastcgi_param        SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_param        APPLICATION_ENV development;
      fastcgi_param        HTTPS $https;
  }
}

【问题讨论】:

    标签: nginx apache2 zend-framework2 special-characters http-redirect


    【解决方案1】:

    您可以通过在 .htaccess 文件中设置正确的重写规则来实现预期的 URL 重写行为。

    我建议你看看rewriteflags,尤其是B flag

    【讨论】:

    • 抱歉,我忘了提供一个重要信息——有两种环境:使用 nginx 的测试环境和开启的实时环境。刚刚编辑了问题。
    • 感谢您的回答!旗帜? B (escape backreferences)?你能解释一下,它将如何解决这个问题?
    • 获取上面的维基百科网址,考虑以下规则: RewriteRule ^wiki/(.*)$ /script.php?wiki=$1 [B] 这会将以下内容:en.wikipedia.org/wiki/Signal_%28electrical_engineering%29 改写为: en.wikipedia.org/wiki/Signal_(electrical_engineering)
    • 我刚刚尝试过:RewriteRule course/^([0-9]+)-([.()-_a-zA-Z0-9&amp;#37;]+)$ /course/$1-$2 [B],但它不工作。这里有什么问题?
    【解决方案2】:

    您应该向我们展示您的 nginx fast_cgi 配置。

    它们是为 PHP 设置 PATH_INFO 的几种方法,这是包含 ZF 必须管理的路径的字符串。

    一种方法是:

    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    

    this post看来,您似乎也可以使用这种方式(命名捕获)来避免 PATH_INFO 内容的所有 urlencoding:

    location ~ ^(?<SCRIPT_FILENAME>.+\.php)(?<PATH_INFO>.+)$ {
    (...)
    fastcgi_param PATH_INFO $PATH_INFO;
    

    因此,至少您会检测到问题是来自于 urlencoding 过多还是不足。

    通过避免来自网络服务器的 urlencoding(以及对 apache 执行相同操作),您可以在 PHP 端管理路径的 urldecoding。因为这一次您知道它永远不会被 urldecoded,并且您必须在 php 中执行它 - 或者您可能必须对它进行 urlencode 它 - 您必须管理路径可能在两个版本中出现的事实。

    对于Zend Framework Router 来说,这可能是一份不错的工作。路由器的工作之一是避免诸如 .htaccess 在 apache 中重写规则之类的事情,并以稳定且独立于 Web 服务器的方式管理应用程序中的 url。

    第一步是测试路径字符串并检测是否需要进行 url 编码。 当然,如果您在同一字符串中发送带有 url 编码和 url 解码字符混合的 url,事情会变得更加困难,因为您将无法决定(但对于网络服务器来说也是如此)。在您的示例中,您使用的括号不是在生成的编码 url 中编码而是在 wikipedia 示例中编码,您的应用程序必须选择一个策略 for the rfc protected characters

    【讨论】:

    • 感谢您的回答!我很确定这不是 ZF2 问题,因为我也遇到了路由问题并解决了它们(请参阅 herehere)。 URI 中带有(未转义的)特殊字符的请求不会到达应用程序。我目前在使用我的 nginx 虚拟机时遇到了一些问题。当我解决 VM 问题时,我将提供我的 fast_cgi 配置。
    • 三周后... :) 我终于解决了 VM 的问题,刚刚用 nginx vhost 设置更新了我的问题。我已经尝试了这两种解决方案: 1. fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_param PATH_INFO $fastcgi_path_info; -- 不收费; 2.location ~ ^(?&lt;SCRIPT_FILENAME&gt;.+\.php)(?&lt;PATH_INFO&gt;.+)$ {(而不是location ~ \.php$ {)和fastcgi_param PATH_INFO $PATH_INFO;——不再渲染PHP,我可以下载PHP文件了。
    猜你喜欢
    • 2013-09-14
    • 2019-10-08
    • 2021-09-20
    • 2011-05-16
    • 2017-10-24
    • 1970-01-01
    • 2010-10-06
    • 2013-01-14
    • 1970-01-01
    相关资源
    最近更新 更多