Php mod_重写和带空格的超链接

Php mod_重写和带空格的超链接,php,regex,apache,.htaccess,mod-rewrite,Php,Regex,Apache,.htaccess,Mod Rewrite,因此,我绝对不是htaccess专家,但我已经成功地为我正在制作的webiste整合了以下代码: Options -Indexes +Includes <IfModule mod_rewrite.c> RewriteEngine on RewriteBase / RewriteCond %{REQUEST_URI}::$1 ^(.*?/)(.*)::\2$ RewriteRule ^(.*)$ - [E=BASE:%1] RewriteRule ^\.htaccess$ - [F]

因此,我绝对不是htaccess专家,但我已经成功地为我正在制作的webiste整合了以下代码:

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>
选项-索引+包括
重新启动发动机
重写基/
RewriteCond%{REQUEST_URI}:$1^(.*?/)(.*):\2$
重写规则^(.*)-[E=基:%1]
重写规则^\.htaccess$-[F]
重写规则^$/%{ENV:BASE}/index.php?id=home
重写条件%{REQUEST\u URI}!\。php$[NC]
重写cond%{REQUEST_FILENAME}-s
重写cond%{REQUEST_FILENAME}-D
重写规则^(.*)/$$1[R=301,L]
重写规则^([a-zA-Z0-9]*)$/%{ENV:BASE}/index.php?id=$1[QSA,L]
它基本上将
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
,这会把一切都搞砸

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

空间和编码似乎有问题。如何使超链接正常工作

--编辑-- 多亏了elcodedocle发布的教程,我只是在上一条规则的正则表达式中添加了反斜杠:
^([a-zA-Z0-9/]*)$
,即使这不是最好的方法。然后我注意到最后一条规则中的
[L]
标志。我删除了它,因为这不应该是最后一条规则(不知道它为什么会出现在那里…),现在它工作了!嗯,有点

现在,如果URL末尾有一个尾随斜杠,它将不再工作。可能是因为删除了规则中的
[L]
标志,但我不知道如何修复此问题…

请尝试更改:

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]

(这是一个猜测,但它是您的规则中唯一一个与
%
有关的问题)

[编辑]未编码的空格。所有浏览器都会强制执行空格禁令,因为在通过http协议发送请求之前,浏览器会将每个空格转换为
%20
。有关在mod_rewrite中处理这些问题的解决方法,请参见:

由于URL不能有空格(除了%20),请使用下划线或 用连字符替换它们。如果您必须在中使用空格(%20) 您的URI,您可以将它们包含在范围内的正则表达式中 定义为{space},即([a-zA-Z\]+)。然而,这并非如此 建议

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

sedspace.sh

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

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

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

使用.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>
选项-索引+包含-多视图
重新启动发动机
RewriteCond%{REQUEST_URI}:$1^(.*?/)(.*):\2$
重写规则^(.*)-[E=基:%1]
重写条件%{REQUEST\u URI}!\。php$[NC]
重写cond%{REQUEST_FILENAME}-s
重写cond%{REQUEST_FILENAME}-D
重写规则^(.*)/$%{ENV:BASE}$1[R=302,L,NE]
重写规则^\.htaccess$-[F]
重写规则^$/%{ENV:BASE}/index.php?id=home[L,QSA]
重写cond%{REQUEST_FILENAME}-D
重写cond%{REQUEST_FILENAME}-F
重写规则^(+?)/?$%{ENV:BASE}index.php?id=$1[QSA,L]

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

href=“/home”
是绝对的,它意味着
www.example.com/home
href=“home”
是相对变量,表示
www.example.com/some dir/sub folder/home
。URI中的特殊字符不应影响此操作。请参阅。另外,关于您的
/home
链接问题:通过将
/
作为
href
中的第一个字符,您告诉服务器您想要相对于根目录
example.com
的URL。如果您想要相对于目录树中当前位置的
home
,则只需使用
home
,不带前导
/
。或者,如果您希望链接始终指向
/some dir/sub folder/home
,无论您在何处,请将其用作您的
href
。哦,该死,对不起,实际上代码中
home
之前没有任何
/
,只是输入错误。但是,我如何告诉mod_rewrite如何处理这些编码空间呢?很抱歉,如果这是一个愚蠢的问题,但我似乎不明白为什么它不能处理URL中的空格。这个.htaccess文件位于哪里?它始终与index.php文件位于同一位置。对不起,忘了提。我以前试过,又试了一次,但不幸的是,没有任何变化。这也是我的第一个猜测。找到了一个解决此问题的教程,并用它的建议编辑了我的答案。根据教程的建议,您将得到%20而不是空格,并且在应用其他规则之前,您必须将其替换为空格。我已经相应地更新了我的答案。在我看来,您使用的斜杠是错误的,我想您需要的是反斜杠
\
而不是reg