如何replaceHTTP请求URI中的特殊字符?

在基于Zend Framework 2的网站上(在nginx上的testing环境和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 

并总是得到你想要的网页。

有人知道,如何实现这样的行为(“维基百科”)? (也许用HTTPredirect.htaccess规则?)


更新:

的/ etc / nginx的/ AX-共同的虚拟主机

 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; } } 

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

我建议你看一下rewriteflags ,尤其是B标志

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

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

一种方法是:

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

从这个帖子看来,你也可以使用这种方式(命名捕获)来避免所有的PATH_INFO内容的urlencoding:

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

所以至少你会发现问题是由于有太多或者没有足够的urlencoding。

通过避免从网络服务器urlencoding(并通过做相同的Apache)你可以在PHP端管理路径的urldecoding。 正如这次你知道它永远不会被urldecoded,并且你将不得不在PHP中做 – 或者你可能需要urlencode – weel你将不得不管理的事实,路径可能会在两个版本。

这对Zend Framework路由器来说可能是一个不错的工作。 路由器的工作之一就是避免像apache中的.htaccess重写规则这样的事情,并以稳定的,无需网络服务器的方式来管理应用程序中的url。

第一步是测试路径字符串,并检测是否需要进行网址编码。 当然,如果你在同一个字符串中使用url编码和url解码的字符混合发送url,事情会变得更加困难,因为你将无法决定(但是对于web服务器来说是一样的)。 而在你的例子中,你使用了在生成的编码url中没有被urlencoded的括号,但是在wikipedia例子中编码,你的应用程序将不得不为rfc保护字符选择一个策略。