我实际上RewriteMap
在 vhost 中使用了一条指令来重定向 800 个 URL 列表。它运行良好:
RewriteEngine On
RewriteMap redirects dbm=db:/data/apps/project/current/configuration/etc/httpd/conf/redirects.db
RewriteCond ${redirects:$1} !=""
RewriteRule ^(.*)$ ${redirects:$1} [redirect=permanent,last]
我使用redirect.txt
包含映射的文件。然后将其转换为数据库文件:
httxt2dbm -f db -i /data/apps/project/current/configuration/etc/httpd/conf/redirects.txt -o /data/apps/project/current/configuration/etc/httpd/conf/redirects.db
例如对于这种 URL,是可以的:
/associations/old_index.php /
但是当 URL 包含空格时它不起作用:(我猜其他特殊字符也是一样的)
/Universités%20direct /
这个案子该如何处理?
答案1
一种解决方法可能是在内部重写包含空间改为连字符(将空格替换为连字符),然后将带连字符的 URL 包含在重写映射中。
如果您只有一些 URL 在 URL 内包含单个空格,那么您可以在现有指令之前使用类似以下指令:
RewriteRule ^(.+)\s(.+)$ $1-$2
然后在重写映射中使用以下内容:
/Universités-direct /
更新:如果您的 URL 包含两个空格(例如/the force awakens
),并且有些 URL 包含一个空格,那么您可以添加一条附加规则:
RewriteRule ^(.+)\s(.+)\s(.+)$ $1-$2
RewriteRule ^(.+)\s(.+)$ $1-$2
这些规则确实假设您的 URL 不以空格结尾。并且任何 URL 都不能有多个连续的空格。
如果有三个空格,则在上述规则之前添加另一条规则......
RewriteRule ^(.+)\s(.+)\s(.+)\s(.+)$ $1-$2
我倾向于使用多个(简单)规则来实现这一点,而不是通用的“在单个规则中转换所有内容”,除非您特别需要。通用规则将递归运行,将多个空格缩减为单个字符。您还可能需要其他标志(即DPI
)来防止 Apache 中已知的重写错误。
答案2
您可以使用第二个重写映射,内部函数“escape”将空格转换为%20:
RewriteMap ec int:escape
RewriteMap redirects dbm=db:/data/apps/project/current/configuration/etc/httpd/conf/redirects.db
RewriteCond ${redirects:${ec:$1}} !=""
RewriteRule ^(.*)$ ${redirects:${ec:$1}} [redirect=permanent,last]
然后在您自己的重写映射数据库中您可以拥有:
/Universités-direct%20/
这样就应该匹配了。
答案3
您可以通过从 %{THE_REQUEST} 变量中提取编码的 URI 并使用它来进行查找来解决这个问题。当然,您需要将编码的 URI 放入映射中。如下所示:
重写引擎开启 RewriteMap 重定向 dbm=db:/data/apps/project/current/configuration/etc/httpd/conf/redirects.db RewriteCond %{THE_REQUEST} "\w+ ([^ ]+)" 重写规则 ^-[E=MYVAR:%1] 重写条件 ${redirects:%{ENV:MYVAR}} !="" 重写规则 ^ ${redirects:%{ENV:MYVAR}} [redirect=permanent,last] [B]
不过,我只用基于文本的地图而不是数据库地图进行了测试。如果您必须处理带有查询字符串的 URL,则可能需要进行修改。