mod_rewrite和带空格的超链接

时间:2014-06-19 14:15:59

标签: php regex apache .htaccess mod-rewrite

所以我不是.htaccess专家,绝不是,但我已经设法将这些代码放在一起,为我所做的网站编写:

Options -Indexes +Includes
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]
RewriteRule ^\.htaccess$ - [F]
RewriteRule ^$ /%{ENV:BASE}/index.php?id=home
RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [R=301,L]
RewriteRule ^([a-zA-Z0-9]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]
</IfModule>

它基本上将www.example.com/some/dir/index.php?id=home更改为www.example.com/some/dir/home,而前几条规则正在创建某种相对路径值,因此每次更改基本文件夹时我都不必更改RewriteBase(这对这个项目很重要!)。

它工作得非常好,但现在我遇到了一个问题,即URL中必须有空格,如www.example.com/some dir/sub folder/home,这会让一切都搞乱。

如果您点击页面上的链接(例如&#34; href="home"&#34;),则会重定向到www.example.com/home而不是www.example.com/some dir/sub folder/home显然是404错误(即使它没有空格也能正常工作!)。我发现如果右键单击&gt; &#34;将链接复制到剪贴板&#34;即使它在地址栏中显示已解码的版本,它也会成为编码版本www.example.com/some%20dir/sub%20folder/home但是如果手动输入解码后的版本www.example.com/some dir/sub folder/home,它仍能正常工作。

空格和编码似乎有问题。如何让我的超链接正常工作?

- 编辑 - 感谢elcodedocle发布的教程,我只是在最后一条规则中向正则表达式添加了反斜杠空格:^([a-zA-Z0-9/ ]*)$,即使它不是最好的方法。然后我注意到倒数第二个规则中的[L]标志。我删除了它,因为这不应该是最后一条规则(不知道为什么它首先在那里......)现在它可以工作了!好吧,有点......

现在,如果网址末尾有一个尾随斜杠,那么它将不再起作用。 Probabply因为删除了规则中的[L]旗帜,但我不知道如何解决这个问题...

2 个答案:

答案 0 :(得分:2)

让你的.htaccess像这样:

Options -Indexes +Includes -MultiViews

<IfModule mod_rewrite.c>
RewriteEngine on

RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$
RewriteRule ^(.*)$ - [E=BASE:%1]

RewriteCond %{REQUEST_URI} !\.php$ [NC]
RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ %{ENV:BASE}$1 [R=302,L,NE]

RewriteRule ^\.htaccess$ - [F]

RewriteRule ^$ /%{ENV:BASE}/index.php?id=home [L,QSA]

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+?)/?$ %{ENV:BASE}index.php?id=$1 [QSA,L]
</IfModule>

这在您在问题中描述的所有测试用例中都可以正常工作,例如处理空格,尾部斜杠等。

答案 1 :(得分:1)

尝试更改:

RewriteRule ^([a-zA-Z0-9]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]

RewriteRule ^([a-zA-Z0-9%]*)$ /%{ENV:BASE}/index.php?id=$1 [QSA,L]

(这是一个疯狂的猜测,但它是唯一一个与%有问题的规则

[编辑] 未编码的空格are not allowed in URIs。禁止空间由所有浏览器强制执行,因为它们会在通过http协议发送请求之前将每个空间转换为%20。在this tutorial

中描述了在mod_rewrite中处理它们的变通方法
  

由于网址不能包含空格(%20除外),因此请使用下划线或   连字符替换它们。如果你绝对必须使用空格(%20)   您的URI,您可以将它们包含在范围内的正则表达式中   定义为{space},即([a-zA-Z \] +)。但是,这不是   宜。

[EDIT2] 如果这不起作用,您可能需要将%20翻译成空格,然后应用其他规则。这是基于this answer的黑客,您可以尝试:

sedspace.sh

#!/bin/sh
sed -u 's/%20/ /g'

.htaccess

...
RewriteMap sed-space prg:sedspace.sh
RewriteRule ^(.*)$ ${sed-space:$1}
...

(确保sedspace.sh是可执行的)