我在使用超级简单的htaccess重定向时遇到了一些困难。
我想做的就是重写一切,除了几个文件。
htaccess看起来像这样:
RewriteEngine On
RewriteCond %{REQUEST_URI} !sitemap
RewriteCond %{REQUEST_URI} !robots
RewriteRule ^(.*)$ http://example.com/$1 [L,R=301]
有效的部分是所有内容都应该重定向到新域。我也可以在不转发的情况下访问robots.txt,但不能访问sitemap.xml。如果我尝试转到sitemap.xml,则域会继续转发并在新域上打开站点地图文件。
在尝试“忽略”index.html时,我遇到了同样的问题。我可以忽略机器人,我可以忽略备用的html或php文件,但如果我想忽略index.html,则正则表达式失败。
由于我实际上无法查看REQUEST_URI变量中的内容,我的猜测是某种方式index.html和sitemap.xml是某种“特殊”文件,它们最终不会出现在REQUEST_URI中?我知道这是因为一个愚蠢的测试。如果我选择忽略index.html:
RewriteCond %{REQUEST_URI} !index.html
然后,如果我输入example.com/index.html,我将被转发。但是,如果我只输入example.com/,则忽略实际工作,它会显示index.html的内容而不转发!
当我选择忽略正则表达式“index.html”时,它只在“index.html”实际上没有在地址栏中输入时才有效!?!
它变得更加怪异!我应该输入类似example.com/index.html?option=value的内容,然后忽略规则可以正常工作,当有类似这样的属性时我不会转发。但是index.html本身不起作用,然后只有斜杠根,规则再次起作用。
我完全糊涂了!为什么看起来REQUEST_URI无法看到像index.html和sitemap.xml这样的文件名?我已经谷歌搜索了2天,不仅我不知道这是否属实,但我似乎找不到任何实际上提供这些htaccess服务器变量实际包含的例子的网站!
谢谢!
答案 0 :(得分:0)
对于index.html
问题,您可能只需要转义点(index\.html
)。您位于RewriteCond右侧的regex模式匹配区域。在其中存在未转义的点时,请求中的该位置将需要有一个字符以进行匹配,而没有匹配,因此您将不匹配,并且会导致不必要的转发。
对于sitemap
不匹配的问题,您可以通过仅创建一个空的伪文件(以避免404抛出),然后在.htaccess的顶部进行重定向,来查看REQUEST_URI实际包含的内容。然后,在浏览器URL中,键入任何您想查看其REQUEST_URI的内容,它将显示在地址栏中。
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^ /test.php?var=%{REQUEST_URI} [NE,R,L]
使用简单的测试方法向MrWhite信用。
希望这会显示URL中的sitemap
最终会以其他形式结束,因此至少会部分解释为什么应该为模式时,它不是模式匹配并阻止重定向的原因-匹配并防止重定向。
我还将通过确保服务器没有使用自定义301指令(无论出于何种原因使sitemap
表现异常)进行测试。将其放在该测试的.htaccess顶部。
ErrorDocument 301 default
答案 1 :(得分:0)
我的猜测是index.html和sitemap.xml某种程度上不是以REQUEST_URI结尾的“特殊”文件吗?
这不是事实。对任何请求的URL都没有这种特殊处理。 REQUEST_URI
服务器变量包含请求的URL路径(仅)。显然,这不包括方案+主机名和任何查询字符串(在其自己的变量中可用)。
但是,如果在此之前有任何其他mod_rewrite指令(包括服务器配置)来重写URL,则REQUEST_URI
服务器变量也会被更新以反映重写的URL。
index.html
(目录索引) index.html
可能是一个特例。但是,如果您明确要求将index.html
作为URL本身的一部分(就像您正在做的那样),那么这将不适用。
另一方面,如果您正在请求目录,例如。 http://example.com/subdir/
并依靠mod_dir发出目录索引的内部子请求(即index.html
),则REQUEST_URI
变量可能包含或可能不包含index.html
-取决于版本您正在使用Apache(2.2 vs 2.4)。在Apache 2.2上,首先执行mod_dir,因此您需要检查/subdir/index.html
。但是,在Apache 2.4上,首先执行mod_rewrite,因此您只需检查请求的URL:/subdir/
。两者都比较安全,特别是如果您有其他重写操作,并且有可能再次通过重写引擎时。
但是,这种情况下最可能的原因仅仅是缓存问题。如果301重定向以前没有这些例外,则可能是这些重定向已被浏览器缓存。 301(永久)重定向由浏览器永久缓存,并且可能导致测试问题(以及也缓存了这些重定向的用户-不幸的是,您无能为力。)
RewriteCond %{REQUEST_URI} !(sitemap|index|alternate|alt) [NC] RewriteRule .* alternate.html [R,L]
您在注释中显示的示例进一步暗示了一个缓存问题,因为与问题中发布的结果相比,sitemap
的结果有所不同。 (它似乎在您的第二个示例中预期的那样工作。)
@zzzaaabbb提到了一种检查Apache服务器变量值的方法。 (请注意,Apache服务器变量REQUEST_URI
与同名的PHP变量不同。)您还可以将Apache服务器变量的值分配给环境变量,该变量随后可以在您的应用程序代码中读取。 / p>
例如:
RewriteRule ^ - [E=APACHE_REQUEST_URI:%{REQUEST_URI}]
然后,您可以在服务器端代码中检查APACHE_REQUEST_URI
环境变量的值。请注意,如果您进行了其他任何重写,导致重新写入过程重新开始,那么您可能会获得多个env变量,每个变量的前缀为REDIRECT_
。