Kyl*_*ndt 275 mod-rewrite redirect redirection 301-redirect apache-2.2
这是一个关于 Apache 的 mod_rewrite的规范问题。
更改请求 URL 或将用户重定向到与他们最初请求的 URL 不同的 URL 是使用 mod_rewrite 完成的。这包括以下内容:
关于 Mod_Rewrite 规则你想知道但又不敢问的一切!
我怎样才能成为编写 mod_rewrite 规则的专家?
测试规则的地方
该htaccess的测试网站是玩弄你的规则,并测试他们的好地方。它甚至会显示调试输出,因此您可以查看匹配的内容和不匹配的内容。
sys*_*138 235
mod_rewrite 有一些影响处理的特定排序规则。在做任何事情之前,RewriteEngine On需要给出指令,因为这会打开 mod_rewrite 处理。这应该在任何其他重写指令之前。
RewriteCond前面RewriteRule使 ONE 规则受条件约束。任何以下 RewriteRules 都将被处理,就好像它们不受条件约束一样。
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html $/blog/$1.sf.html
Run Code Online (Sandbox Code Playgroud)
在这个简单的例子中,如果 HTTP 引用来自 serverfault.com,将博客请求重定向到特殊的 serverfault 页面(我们就是那么特殊)。但是,如果上面的块有一个额外的 RewriteRule 行:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html $/blog/$1.sf.html
RewriteRule $/blog/(.*)\.jpg $/blog/$1.sf.jpg
Run Code Online (Sandbox Code Playgroud)
所有 .jpg 文件都将转到特殊的 serverfault 页面,而不仅仅是那些带有指示它来自此处的引用的文件。这显然不是这些规则编写方式的意图。它可以通过多个 RewriteCond 规则来完成:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html /blog/$1.sf.html
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.jpg /blog/$1.sf.jpg
Run Code Online (Sandbox Code Playgroud)
但可能应该使用一些更棘手的替换语法来完成。
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg) /blog/$1.sf.$2
Run Code Online (Sandbox Code Playgroud)
更复杂的 RewriteRule 包含处理条件。最后一个括号(html|jpg)告诉 RewriteRule 匹配html或jpg,并在重写的字符串中将匹配的字符串表示为 $2。这在逻辑上与前一个块相同,有两个 RewriteCond/RewriteRule 对,它只是在两行而不是四行上完成。
多个 RewriteCond 行是隐式 AND 运算,并且可以显式 OR 运算。处理来自 ServerFault 和超级用户(显式 OR)的引用:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$) [OR]
RewriteCond %{HTTP_REFERER} ^https?://superuser\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg) /blog/$1.sf.$2
Run Code Online (Sandbox Code Playgroud)
使用 Chrome 浏览器提供 ServerFault 引用的页面(隐式 AND):
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*Chrome.*$
RewriteRule ^/blog/(.*)\.(html|jpg) /blog/$1.sf.$2
Run Code Online (Sandbox Code Playgroud)
RewriteBase也是特定于订单的,因为它指定了以下RewriteRule指令如何处理它们的处理。它在 .htaccess 文件中非常有用。如果使用,它应该是 .htaccess 文件中“RewriteEngine on”下的第一个指令。拿这个例子:
RewriteEngine On
RewriteBase /blog
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg) $1.sf.$2
Run Code Online (Sandbox Code Playgroud)
这告诉 mod_rewrite 它当前处理的这个特定 URL 是通过http://example.com/blog/而不是物理目录路径 (/home/$Username/public_html/blog) 到达的,并相应地对其进行处理。因此,它RewriteRule认为它的字符串开始位于 URL 中的“/blog”之后。这是同一个东西,用两种不同的方式写成。一个带有 RewriteBase,另一个没有:
RewriteEngine On
##Example 1: No RewriteBase##
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule /home/assdr/public_html/blog/(.*)\.(html|jpg) $1.sf.$2
##Example 2: With RewriteBase##
RewriteBase /blog
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg) $1.sf.$2
Run Code Online (Sandbox Code Playgroud)
如您所见,RewriteBase允许重写规则利用网站内容路径而不是网络服务器,这可以使编辑此类文件的人更容易理解它们。此外,它们可以使指令更短,这具有美学吸引力。
RewriteRule 本身具有用于匹配字符串的复杂语法。我将在另一节中介绍标志(例如 [PT])。因为系统管理员通过示例学习比阅读手册页更频繁,所以我将给出示例并解释他们的工作。
RewriteRule ^/blog/(.*)$ /newblog/$1
Run Code Online (Sandbox Code Playgroud)
该.*构造匹配任何单个字符 ( .) 零次或多次 ( *)。将它括在括号中告诉它提供与 $1 变量匹配的字符串。
RewriteRule ^/blog/.*/(.*)$ /newblog/$1
Run Code Online (Sandbox Code Playgroud)
在这种情况下,第一个 .* 没有包含在括号中,因此不会提供给重写的字符串。此规则删除新博客站点上的目录级别。(/blog/2009/sample.html 变成 /newblog/sample.html)。
RewriteRule ^/blog/(2008|2009)/(.*)$ /newblog/$2
Run Code Online (Sandbox Code Playgroud)
在这种情况下,第一个括号表达式设置了一个匹配组。这变成了 $1,这不是必需的,因此不会在重写的字符串中使用。
RewriteRule ^/blog/(2008|2009)/(.*)$ /newblog/$1/$2
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们在重写的字符串中使用 $1。
RewriteRule ^/blog/(20[0-9][0-9])/(.*)$ /newblog/$1/$2
Run Code Online (Sandbox Code Playgroud)
此规则使用指定字符范围的特殊括号语法。[0-9] 匹配数字 0 到 9。此特定规则将处理从 2000 年到 2099 年的年份。
RewriteRule ^/blog/(20[0-9]{2})/(.*)$ /newblog/$1/$2
Run Code Online (Sandbox Code Playgroud)
这与前面的规则做同样的事情,但 {2} 部分告诉它匹配前面的字符(在这种情况下是括号表达式)两次。
RewriteRule ^/blog/([0-9]{4})/([a-z]*)\.html /newblog/$1/$2.shtml
Run Code Online (Sandbox Code Playgroud)
这种情况将匹配第二个匹配表达式中的任何小写字母,并尽可能多地匹配字符。该\.构造告诉它将句点视为实际句点,而不是前面示例中的特殊字符。但是,如果文件名中有破折号,它会中断。
RewriteRule ^/blog/([0-9]{4})/([-a-z]*)\.html /newblog/$1/$2.shtml
Run Code Online (Sandbox Code Playgroud)
这会捕获带有破折号的文件名。但是,作为-括号表达式中的特殊字符,它必须是表达式中的第一个字符。
RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html /newblog/$1/$2.shtml
Run Code Online (Sandbox Code Playgroud)
此版本使用字母、数字或文件名中的字符捕获任何文件-名。这是在括号表达式中指定多个字符集的方式。
RewriteRule ^/blog/([0-9]{4})/([-a-z]*).\html /newblog/$1/$2.shtml [L]
Run Code Online (Sandbox Code Playgroud)
标志位于[L]上述表达式的末尾。可以使用多个标志,用逗号分隔。链接的文档描述了每一个,但无论如何它们都在这里:
L = 最后。一旦这个匹配,停止处理 RewriteRules。订单很重要!
C = 链。继续处理下一个 RewriteRule。如果此规则不匹配,则不会执行下一条规则。稍后会详细介绍。
E = 设置环境变量。Apache 有多种环境变量可以影响 Web 服务器的行为。
F = 禁止。如果此规则匹配,则返回 403-Forbidden 错误。
G = 不见了。如果此规则匹配,则返回 410-Gone 错误。
H = 处理程序。强制处理请求,就好像它是指定的 MIME 类型一样。
N = 下一个。强制规则重新开始并重新匹配。当心!可能导致循环。
NC = 无。允许jpg匹配jpg和JPG。
NE = 无法逃脱。防止将特殊字符 (. ? # & 等) 重写为它们的十六进制代码等效项。
NS = 无子请求。如果您使用服务器端包含,这将阻止与包含文件的匹配。
P = 代理。强制规则由 mod_proxy 处理。透明地提供来自其他服务器的内容,因为您的网络服务器会获取它并重新提供它。这是一个危险的标志,因为一个写得不好的标志会将您的网络服务器变成一个开放代理,这很糟糕。
PT = 通过。在 RewriteRule 匹配中考虑 Alias 语句。
QSA = QSAppend。当原始字符串包含查询 ( http://example.com/thing?asp=foo) 将原始查询字符串附加到重写的字符串中。通常它会被丢弃。对于动态内容很重要。
R = 重定向。提供到指定 URL 的 HTTP 重定向。还可以提供准确的重定向代码 [R=303]。非常类似于RedirectMatch,它更快,应尽可能使用。
S = 跳过。跳过此规则。
T = 类型。指定返回内容的 MIME 类型。与AddType指令非常相似。
你知道我怎么说这RewriteCond适用于一个且只有一个规则吗?好吧,你可以通过链接来解决这个问题。
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html /blog/$1.sf.html [C]
RewriteRule ^/blog/(.*)\.jpg /blog/$1.sf.jpg
Run Code Online (Sandbox Code Playgroud)
因为第一个 RewriteRule 有 Chain 标志,第二个 rewrite-rule 将在第一个执行时执行,也就是在匹配前一个 RewriteCond 规则时。如果 Apache 正则表达式让你的大脑受到伤害,这很方便。但是,从优化的角度来看,我在第一部分中提到的一体式方法更快。
RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html /newblog/$1/$2.shtml
Run Code Online (Sandbox Code Playgroud)
这可以通过标志变得更简单:
RewriteRule ^/blog/([0-9]{4})/([-0-9a-z]*)\.html /newblog/$1/$2.shtml [NC]
Run Code Online (Sandbox Code Playgroud)
此外,一些标志也适用于 RewriteCond。值得注意的是,NoCase。
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$) [NC]
Run Code Online (Sandbox Code Playgroud)
将匹配“ServerFault.com”
dan*_*ree 40
mod_rewrite 规则的基本格式和结构是什么?
我将遵循 sysadmin1138 在这些方面的出色回答。
我需要牢牢掌握正则表达式的什么形式/风格?
除了 sysadmin1138 概述的语法顺序、语法匹配/正则表达式和 RewriteRule 标志之外,我相信值得一提的是 mod_rewrite 基于 HTTP 请求标头和 Apache 的配置公开了 Apache 环境变量。
我会推荐AskApache 的 mod_rewrite 调试教程,以获得可能可用于 mod_rewrite 的完整变量列表。
编写重写规则时最常见的错误/陷阱是什么?
RewriteRule 的大多数问题源于对 PCRE 语法的误解/未能正确转义特殊字符或缺乏对用于匹配的变量内容的了解。
典型问题和建议的故障排除:
IfModule有条件地包装指令以避免这种情况),检查指令语法,注释掉指令直到发现问题什么是测试和验证 mod_rewrite 规则的好方法?
首先,查看您计划匹配的环境变量的内容 - 如果您安装了 PHP,这就像将以下块添加到您的应用程序一样简单:
<?php
var_dump($_SERVER);
?>
Run Code Online (Sandbox Code Playgroud)
...然后编写您的规则(最好用于在开发服务器上进行测试)并在您的 Apache ErrorLog文件中记录任何不一致的匹配或活动。
对于更复杂的规则,请使用 mod_rewrite 的RewriteLog指令将活动记录到文件并设置RewriteLogLevel 3
我应该注意 mod_rewrite 规则对 SEO 或性能的影响吗?
AllowOverride all影响服务器性能,因为 Apache 必须检查.htaccess文件并解析每个请求的指令 - 如果可能,将所有指令保留在您站点的 VirtualHost 配置中,或者.htaccess仅对需要它们的目录启用覆盖。
Google 的网站管理员指南明确指出:“不要欺骗您的用户或向搜索引擎展示与向用户展示的内容不同的内容,这通常被称为‘伪装’。” - 避免创建 mod_rewrite 指令来过滤搜索引擎机器人。
搜索引擎机器人喜欢一个1:1的内容:URI的映射(这是排名链接内容的基础) -如果你正在使用mod_rewrite创建临时重定向或您所服务在多个URI的内容相同,考虑指定一个标准URI内您的 HTML 文档。
是否存在 mod_rewrite 看起来是适合这项工作的正确工具但不是的常见情况?
这本身就是一个巨大的(并且可能有争议的)话题 - 更好地(恕我直言)根据具体情况解决使用问题,并让提问者确定建议的解决方案是否适合他们的需求。
有哪些常见的例子?
AskApache 的 mod_rewrite Tricks and Tips涵盖了几乎所有定期弹出的常见用例,但是,给定用户的“正确”解决方案可能取决于用户配置和现有指令的复杂程度(这就是为什么它通常是一个每当出现 mod_rewrite 问题时,看看用户有哪些其他指令是个好主意)。
Ter*_*ryE 21
像许多管理员/开发人员一样,我多年来一直在与复杂的重写规则作斗争,并且对现有的 Apache 文档不满意,所以我决定作为一个个人项目深入了解mod_rewrite实际工作以及与 Apache 其余部分的交互核心,所以在过去的几个月里,我一直在使用strace+ 钻探源代码来检测测试用例,以处理所有这些。
.htaccess处理与 PerDir ( ) 处理截然不同。我会说,正因为如此,你几乎需要将重写用户社区分为两类,并将它们视为完全独立的:
那些对 Apache config 具有 root 访问权限的人。这些通常是具有应用程序专用服务器/VM 的管理员/开发人员,这里的信息非常简单:.htaccess尽可能避免使用文件;在您的服务器或虚拟主机配置中执行所有操作。调试非常容易,因为开发人员可以设置调试并可以访问 rewrite.log 文件。
共享托管服务 (SHS) 的用户。
.htaccess/Perdir 处理,因为没有可用的替代方法。 .htaccess文件以及原因。它没有解释 PerDir 循环的复杂性以及如何避免这种情况。可能还有第三个社区:SHS 提供者的管理和支持人员,他们最终都涉足两个阵营,并不得不承受上述后果。
我已经写了几篇文章风格的博客文章(例如更多关于在 .htaccess 文件中使用重写规则),其中涵盖了很多详细的点,我不会在这里重复以保持这篇文章的简短。我有自己的共享服务,并支持一些专用和 VM FLOSS 项目。我开始使用标准 LAMP VM 作为我的 SHS 帐户的测试工具,但最后我发现最好做一个适当的镜像 VM(在此处描述)。
但是,就管理社区应如何支持.htaccess用户而言,我觉得我们需要开发并提供:
.htaccess重写规则的指南/最佳实践有关如何从规则中获取内置诊断的提示(例如
[E=VAR:EXPR]利用这样的事实EXPR将扩大反向引用($ N或N%),以使其可作为诊断的目标脚本。如果您使用 [OR]、[C]、[SKIP] 和 [L] 标志对重写规则进行局部排序,以便整个重写方案无需利用内部重定向即可工作,那么您可以将以下内容添加为规则 1 以避免所有循环麻烦:
RewriteCond %{ENV:REDIRECT_STATUS} !=""
RewriteRule . - [L]
Run Code Online (Sandbox Code Playgroud)Kri*_*ien 15
使用重写映射
使用重写映射可以做很多事情。Rewritemaps 使用 Rewritemap 指令声明,然后可以在 RewritCond 评估和 RewriteRule 替换中使用。
RewriteMap 的一般语法是:
RewriteMap MapName MapType:MapSource
Run Code Online (Sandbox Code Playgroud)
例如:
RewriteMap examplemap txt:/path/to/file/map.txt
Run Code Online (Sandbox Code Playgroud)
然后,您可以将 mapname 用于这样的构造:
${examplemap:key}
Run Code Online (Sandbox Code Playgroud)
该映射包含键/值对。如果找到键,则替换该值。简单映射只是纯文本文件,但您可以使用哈希映射,甚至 SQL 查询。更多细节在文档中:
http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html#rewritemap
非转义字符串。
您可以使用四个内部映射进行一些操作。特别是未转义的字符串可以派上用场。
例如:我想测试查询字符串中的字符串“café”。但是,浏览器会在将其发送到我的服务器之前对其进行转义,因此我需要弄清楚我希望匹配的每个字符串的 URL 转义版本是什么,或者我可以取消转义它......
RewriteMap unescape int:unescape
RewriteCond %{QUERY_STRING} (location|place)=(.*)
RewriteCond ${unescape:%2} café
RewriteRule ^/find/$ /find/1234? [L,R]
Run Code Online (Sandbox Code Playgroud)
请注意我如何使用一个 RewriteCond 来捕获查询字符串参数的参数,然后使用第二个 rewriteCond 中的映射来取消转义它。然后进行比较。还要注意我如何需要我们 %2 作为重写映射中的键,因为 %1 将包含“位置”或“地点”。当您使用括号对模式进行分组时,它们也将被捕获,无论您是否打算使用捕获的结果...
| 归档时间: |
|
| 查看次数: |
106757 次 |
| 最近记录: |