这是关于Apache的mod_rewrite的规范性问题。这包括诸如以下内容:
将HTTP更改为HTTPS(或相反)
将请求更改为不再存在的页面以进行新的替换。
修改URL格式(例如?id = 3433到/ id / 3433)
基于浏览器,基于引荐来源,基于月亮和太阳的任何可能呈现不同的页面。
您想弄乱URL的任何内容
您想了解的有关Mod_Rewrite规则的所有内容,但都不敢问!
mod_rewrite规则的基本格式和结构是什么?
我需要扎实地理解正则表达式的哪种形式/风格?
什么?编写重写规则时最常见的错误/陷阱是什么?
什么是测试和验证mod_rewrite规则的好方法?
我应该意识到mod_rewrite规则的SEO或性能影响吗?
有普通坐吗
有哪些常见示例?
测试规则的地方
htaccess测试器网站是您试用和测试规则的好地方。它甚至显示调试输出,因此您可以查看匹配的内容和不匹配的内容。
#1 楼
mod_rewrite语法顺序mod_rewrite具有一些影响处理的特定排序规则。在完成任何操作之前,需要先给出
RewriteEngine On
指令,因为这会打开mod_rewrite处理。这应该在任何其他重写指令之前。RewriteCond
之前的RewriteRule
使一个规则受条件限制。以下所有RewriteRules都将被视为不受条件约束。RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html $/blog/.sf.html
在这种简单情况下,如果HTTP引用人来自serverfault.com,则重定向博客请求到特殊的serverfault页面(我们就是这么特殊)。但是,如果上面的代码块有多余的RewriteRule行:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule $/blog/(.*)\.html $/blog/.sf.html
RewriteRule $/blog/(.*)\.jpg $/blog/.sf.jpg
所有.jpg文件都将转到特殊的serverfault页面,而不仅仅是带有引荐来源的页面。从这里来的显然,这不是这些规则的编写方式。可以使用多个RewriteCond规则完成:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html /blog/.sf.html
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.jpg /blog/.sf.jpg
,但可能应该使用一些更复杂的替换语法来完成。
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg) /blog/.sf.
更复杂的RewriteRule包含要处理的条件。最后一个括号
(html|jpg)
告诉RewriteRule匹配html
或jpg
,并在重写的字符串中将匹配的字符串表示为$ 2。从逻辑上讲,它与前一个块相同,只有两个RewriteCond / RewriteRule对,它只在两行而不是四行上执行。要同时处理ServerFault和超级用户的引荐来源网址(明示或):RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$) [OR]
RewriteCond %{HTTP_REFERER} ^https?://superuser\.com(/|$)
RewriteRule ^/blog/(.*)\.(html|jpg) /blog/.sf.
要在Chrome浏览器中为ServerFault引荐的页面提供服务(隐式AND): />
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteCond %{HTTP_USER_AGENT} ^Mozilla.*Chrome.*$
RewriteRule ^/blog/(.*)\.(html|jpg) /blog/.sf.
RewriteBase
也是特定于订单的,因为它指定了以下RewriteRule
指令如何处理它们。在.htaccess文件中,它非常有用。如果使用,它应该是.htaccess文件中“ RewriteEngine on”下的第一个指令。例如:RewriteEngine On
RewriteBase /blog
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg) .sf.
这是告诉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) .sf.
##Example 2: With RewriteBase##
RewriteBase /blog
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^(.*)\.(html|jpg) .sf.
如您所见,
RewriteBase
允许重写规则利用网站的内容路径而不是Web服务器,这可以使他们对编辑此类文件的人更易懂。此外,它们还可以使指令更短,从而具有美观的外观。RewriteRule匹配语法
RewriteRule本身具有用于匹配字符串的复杂语法。我将在另一部分介绍标志(例如[PT]之类的东西)。因为系统管理员比通过阅读手册页通过示例学习的频率更高,所以我将给出示例并解释其功能。
RewriteRule ^/blog/(.*)$ /newblog/
.*
构造匹配任何单个字符( .
)零次或多次(*
)。将其括在圆括号中将指示它提供与$ 1变量匹配的字符串。RewriteRule ^/blog/.*/(.*)$ /newblog/
在这种情况下,第一个。*没有括在括号中,因此没有提供给重写的字符串。此规则将删除新博客站点上的目录级别。 (/blog/2009/sample.html变为/newblog/sample.html)。
RewriteRule ^/blog/(2008|2009)/(.*)$ /newblog/
在这种情况下,第一个括号表达式会设置一个匹配组。这将变成$ 1,这是不需要的,因此不会在重写的字符串中使用。
RewriteRule ^/blog/(2008|2009)/(.*)$ /newblog//
在这种情况下,我们在重写的字符串中使用$ 1。
RewriteRule ^/blog/(20[0-9][0-9])/(.*)$ /newblog//
此规则使用特殊的括号语法指定字符范围。 [0-9]匹配数字0到9。此特定规则将处理2000年到2099年之间的年份。
RewriteRule ^/blog/(20[0-9]{2})/(.*)$ /newblog//
这与以前的规则具有相同的作用,但是{2}部分告诉它两次匹配前一个字符(在这种情况下为方括号表达式)。
RewriteRule ^/blog/([0-9]{4})/([a-z]*)\.html /newblog//.shtml
此大小写将匹配任何小写字母在第二个匹配表达式中,并尽可能使用尽可能多的字符。
\.
构造告诉它将周期视为实际周期,而不是前面示例中的特殊字符。但是,如果文件名中包含破折号,它将断开。RewriteRule ^/blog/([0-9]{4})/([-a-z]*)\.html /newblog//.shtml
这会捕获其中包含破折号的文件名。但是,由于
-
是括号表达式中的特殊字符,因此它必须是表达式中的第一个字符。或文件名中的-
字符。这是在括号表达式中指定多个字符集的方式。RewriteRule标志
重写规则上的标志具有许多特殊含义和用例。
RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html /newblog//.shtml
该标志位于上述表达式结尾处的
[L]
。可以使用多个标志,以逗号分隔。链接的文档描述了每个文档,但是无论如何都在这里:L =最后。一旦匹配,则停止处理RewriteRules。 C =链条。继续处理下一个RewriteRule。如果此规则不匹配,则不会执行下一个规则。 E =设置环境变量。 Apache具有各种可能影响Web服务器行为的环境变量。 F =禁止。如果此规则匹配,则返回403-Forbidden错误。如果此规则匹配,则返回410-Gone错误.H =处理程序。强制将请求当作指定的MIME类型进行处理.N =下一步。强制规则重新开始并重新匹配。小心!可能会导致循环。NC=无大小写。允许
jpg
同时匹配jpg和JPG。 NE =无法逃脱。防止将特殊字符(。?#&等)重写为等效的十六进制代码。NS =无子请求。如果您使用服务器端包含文件,这将阻止与包含文件的匹配.P =代理服务器。强制该规则由mod_proxy处理。透明地从其他服务器提供内容,因为您的Web服务器会获取并重新提供内容。这是一个危险的标志,因为写得不好的标志会将您的Web服务器变成开放代理,这很糟糕。PT=直通。请考虑RewriteRule匹配中的Alias语句。QSA= QSAppend。当原始字符串包含查询(http://example.com/thing?asp=foo)时,请将原始查询字符串附加到重写的字符串中。通常,它将被丢弃。对于动态内容很重要。R =重定向。提供HTTP重定向到指定的URL。也可以提供确切的重定向代码[R = 303]。与RedirectMatch
非常相似,后者速度更快,应尽可能使用。S=跳过。跳过此规则。T =类型。指定返回内容的MIME类型。非常类似于AddType
指令。您知道我说过
RewriteCond
仅适用于一条规则吗?好吧,您可以通过链接解决该问题。RewriteRule ^/blog/([0-9]{4})/([-a-z]*).\html /newblog//.shtml [L]
因为第一个RewriteRule具有Chain标志,所以第二个rewrite-rule将在第一个rewriteRule匹配时执行,即与前一个RewriteCond规则匹配时执行。如果Apache正则表达式使您的大脑受伤,该功能非常方便。但是,从优化的角度来看,我在第一节中提到的多行方法更快。
标志:
RewriteEngine On
RewriteCond %{HTTP_REFERER} ^https?://serverfault\.com(/|$)
RewriteRule ^/blog/(.*)\.html /blog/.sf.html [C]
RewriteRule ^/blog/(.*)\.jpg /blog/.sf.jpg
此外,某些标志也适用于RewriteCond。值得注意的是,NoCase。
RewriteRule ^/blog/([0-9]{4})/([-0-9a-zA-Z]*)\.html /newblog//.shtml
将匹配“ ServerFault.com”
评论
做得好。 [填料]
–EEAA
2010-12-20 19:20
非常好的mod_rewrite和regex入门。 +1。
–周一星期一
2010-12-20 23:24
知道在匹配RewriteRule之后实际上已处理RewriteCond有时会很有用。您可能想在顶部附近说“稍后再说”,在上面说“ RewriteRule之前的RewriteCond使该一个规则服从条件”。您可能要提到,正则表达式是Perl兼容的正则表达式。此外,“ ... RewriteRule认为它是字符串开头的”中,您还有一个多余的撇号。
–丹尼斯·威廉姆森
2010-12-20 23:57
RewriteRule ^ / blog /.*/(.*)$ / newblog / $ 1与第一个目录组件不匹配-默认情况下,rewriterules是贪婪的。 /.*/(.*)匹配/ 1 /(2)/和/ 1/2/3/4/5 /(6)/,因此您需要/ [^ /] * /只匹配第一条路径零件。
–适配器
2012年4月12日12:55在
@ sysadmin1138,我认为这个答案很好,但是如果您通过示例详细说明标志E,N,NS,P,PT和S,则可能会更好,因为这些标志并不明显如何工作等。
–起搏器
2013年8月5日在2:17
#2 楼
mod_rewrite规则的基本格式和结构是什么?
我将在这些方面服从sysadmin1138的出色回答。
我需要扎实的
正则表达式的什么形式/风格?
除了语法顺序,语法匹配/正则表达式以及sysadmin1138概述的RewriteRule标志,我相信值得一提的是mod_rewrite会根据HTTP请求标头和Apache的配置公开Apache环境变量。可以用于mod_rewrite的变量列表。
编写重写规则时最常见的错误/陷阱是什么?
>
RewriteRule的大多数问题源于对PCRE语法的误解/未能正确转义特殊字符或对所用变量的内容缺乏洞察力或匹配。
典型问题和建议的故障排除:
500-内部服务器错误-如果存在,请删除配置文件中的Windows托架控件当前,确保启用了mod_rewrite(在
IfModule
中有条件地包装指令以避免这种情况),检查指令语法,注释掉指令,直到发现问题为止重定向循环-使用RewriteLog和RewriteLogLevel,注释掉指令,直到发现问题
什么是测试和验证mod_rewrite规则的好方法?
首先,请看一下您计划要匹配的环境变量的内容-如果已安装PHP,这就像在应用程序中添加以下代码块一样简单:
<?php
var_dump($_SERVER);
?>
...然后编写您的规则(最好是在开发服务器上进行测试),并注意Apache ErrorLog文件中的任何不一致的匹配或活动。
对于更复杂的规则,请使用mod_rewrite的
RewriteLog
指令将活动记录到文件中并设置RewriteLogLevel 3
mod_rewrite规则I
是否有SEO或性能含义?
AllowOverride all
影响服务器性能,因为Apache必须检查.htaccess
文件并使用每个请求分析指令-如果可能,请将所有指令保留在站点的VirtualHost配置中或启用.htaccess
覆盖Google的《网站管理员指南》明确指出:“不要欺骗用户或向搜索引擎展示与向用户显示的内容不同的内容,这通常被称为“隐藏” 。'“-避免创建用于过滤搜索引擎机器人的mod_rewrite指令。
搜索引擎机器人更喜欢1:1 content:URI映射(这是对内容链接进行排名的基础)-如果您使用mod_rewrite创建临时重定向或您正在提供服务在多个URI下具有相同的内容,请考虑在您的HTML文档中指定一个规范的URI。
是否有常见的情况,其中
mod_rewrite看起来像是正确的
工具,
这本身就是一个巨大的(可能引起争议的)主题-更好地(IMHO)可以根据具体情况解决使用问题,让询问者确定建议的分辨率是否适合他们的需求。
常见示例有哪些?
问问Apache的mod_rewrite技巧和窍门仅涉及关于定期弹出的每个常见用例,但是,给定用户的“正确”解决方案可能取决于用户配置和现有指令的复杂程度(因此,通常最好查看其他哪些指令)每当出现mod_rewrite问题时,用户就位。)
评论
感谢您的AskApache链接。这就是我想要的!
–sica07
11年11月23日在22:14
ASF正式不支持AskApache小丑。他所说的大部分内容值得商or或完全错误。
–适配器
2012年4月12日在12:59
@adaptr请分享您显然知道的高级资源。
– Danlefree
2012年4月13日,0:56
“在常见情况下,mod_rewrite看起来像是适合该工作的工具,但不是吗?” -简单的重定向,其中尚未使用mod_rewrite。请改用mod_alias Redirect或RedirectMatch。另请参阅Apache文档:何时不使用mod_rewrite
–怀特先生
16 Dec 8'在15:27
#3 楼
像许多管理员/开发人员一样,多年来我一直在努力应对复杂的重写规则,并且对现有的Apache文档不满意,因此我决定作为一个个人项目,深入研究mod_rewrite
的实际工作原理并与之交互。 Apache核心,因此在过去的几个月中,我一直在使用strace
+钻探源代码来测试测试用例,以获取所有这些信息的处理方法。需要考虑:重写的某些方面对于服务器配置,虚拟主机,目录,.htaccess处理是通用的,但是某些处理对于根配置(服务器配置,虚拟主机和目录)与PerDir(
.htaccess
)处理相对。可以触发这个。我会这么说,因此您几乎需要将重写用户社区分为两类,并将它们完全分开:
具有root访问权限的用户到Apache配置。这些通常是具有专用服务器/ VM的管理员/开发人员,这里的信息很简单:尽可能避免使用
.htaccess
文件;在服务器或vhost配置中执行所有操作。调试非常容易,因为开发人员可以设置调试并可以访问rewrite.log文件。共享托管服务(SHS)的用户。 由于没有其他选择,因此这些用户必须使用
.htaccess
/ Perdir处理。 更糟的是,此类用户的技能水平(就使用mod_rewrite的regexp驱动的梯形逻辑而言)通常远低于经验丰富的管理员。
Apache和托管服务提供商不提供调试/诊断支持。唯一的诊断信息是成功的重定向,即重定向到错误的URI。或404/500状态代码。这使他们感到困惑和无助。
Apache非常弱,无法解释这种用例的重写工作原理。例如,它没有清楚说明选择哪个PerDir
.htaccess
文件以及原因。它没有解释PerDir骑车的复杂性以及如何避免这种情况。可能存在第三个社区:SHS提供者中的管理员和支持人员最终以在两个营地中站起来,都必须承受以上后果。
我写了几篇文章风格的博客文章(例如,有关在.htaccess文件中使用重写规则的更多信息),其中涵盖了许多详细点,在这里我不再赘述。 。我拥有自己的共享服务,并支持一些专用的VM FLOSS项目。我最初使用标准的LAMP VM作为我的SHS帐户的测试工具,但最后我发现最好做一个合适的镜像VM(在此介绍)。
但是,在管理员社区应如何支持
.htaccess
用户方面,我认为我们需要开发并提供以下内容:重写系统实际上在PerDir处理中起作用。关于如何编写
.htaccess
重写规则的一组准则/最佳实践类似于W3C html解析器的一种基于Web的简单重写脚本解析器,但是用户可以输入相同的测试URI或测试向量,并立即获得重写逻辑流的日志/
关于如何从规则中获取内置诊断的提示(例如
利用
[E=VAR:EXPR]
充分利用了以下事实:EXPR
将扩展反向引用($ N或%N),以使其可作为目标脚本的诊断程序。如果使用[OR],[C],[SKIP]和[L]标志局部地对重写规则进行排序,以便整个重写方案都可以工作而无需利用内部重定向,则可以将以下内容添加为规则1,以避免所有循环麻烦:
RewriteCond %{ENV:REDIRECT_STATUS} !=""
RewriteRule . - [L]
评论
这是有据可查的。为什么说文档没有解释这一点?
–适配器
2012年4月12日12:57
您所要做的就是订阅.htaccess主题,您将看到。大多数初学者无可奈何地感到困惑-他们中的大多数人初次体验LAMP服务,并在共享服务上使用mod_rewrite,因此没有对系统/ vhost配置的根访问权限,并且必须通过.htaccessfile使用每个目录处理。初学者必须“流血”一些重要区别。我将自己视为超级用户,并且仍在发现微妙之处。正如我所说的那样,我必须使用strace和源代码扫描来解决某些方面的问题。 :-(
– TerryE
2012年4月13日在16:25
我完全同意。 “我们需要将重写用户社区分为两类,并将它们完全分开。”一些用户正在使用共享主机,并且需要依赖.htaccess,即使对于专家来说,.htaccess也是非常脆弱,复杂和混乱的。我仍然有麻烦。
–瑞安
17年7月19日在17:05
#4 楼
使用rewritemaprewritemaps可以做很多事情。 Rewritemaps使用Rewritemap指令声明,然后可以在RewritCond评估和RewriteRule替代中使用。
RewriteMap的常规语法是:
RewriteMap MapName MapType:MapSource
例如:
RewriteMap examplemap txt:/path/to/file/map.txt
然后您可以将mapname用于以下结构:
${examplemap:key}
地图包含键/值对。如果找到了密钥,则该值将被替换。简单映射只是纯文本文件,但是您可以使用哈希映射,甚至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]
请注意,我如何使用一个RewriteCond仅捕获查询字符串参数的自变量,然后使用第二个rewriteCond中的映射对其进行转义。然后比较一下。
还请注意,我需要我们如何将%2作为重写映射中的键,因为%1将包含“位置”或“位置”。当您使用括号对模式进行分组时,无论是否计划使用捕获的结果,它们都将被捕获。
评论
最后一句话不太正确。 mod_rewrite正则表达式引擎支持非捕获组,例如(?:location | place),并且在示例中仅捕获一个。
– TerryE
17 Mar 10 '17 at 23:32
#5 楼
编写重写规则时最常见的错误/陷阱是什么?
一个真正简单的陷阱是,当您重写更改外观的URL时路径,例如从
/base/1234/index.html
到/base/script.php?id=1234
。客户端将找不到任何具有指向脚本位置的相对路径的图像或CSS。可以在此常见问题解答中找到许多解决方案。评论
感谢您的链接。尤其是在与不熟悉重写的其他团队成员一起工作时,我发现添加
– kontur
2012年5月20日11:12
评论
这个问题的想法是为所有无尽的mod_rewrite问题提供一个封闭的路径,这些问题使我们的普通用户发疯。这与在serverfault.com/questions/49765/how-does-subnetting-work上进行子网划分非常相似。另外,我真的不希望在这个问题上有太多的投票,相反,他们应该去回答。我不想继续这样做,因为我想确保张贴者对我希望通过mod_rewrite答案来结束所有mod_rewrite问题获得充分的评价。
抱歉,我赞成这个问题。 ;-)我真的认为它需要显示在mod-rewrite标签搜索/过滤器顶部(或附近)。
其他人(tm)应该处理常见的用例。我对他们的了解还不够,无法做到公正。
也许应该将此问题链接到mod-rewrite标签wiki中,以使路径更短。