在我的本地Linux机器上,我正在运行Apache 2.2.15服务器。我想设置一个.htaccess
RewriteRule
,以便在匹配某个URL查询字符串(?print=pdf&redirect=false
)时设置响应头。
示例URL:
www.example.com/page1/?print=pdf&redirect=false
我尝试了不同的方法,但我不知道我做错了什么。正如您所看到的,我试图设置一个在匹配查询字符串时需要设置的环境变量,但它不起作用。以下是我的文件:
RewriteCond %{QUERY_STRING}e ^print=pdf&redirect=false$
RewriteRule ^(.*)$ - [E=IS_CANONICAL:1,L]
Header set Link "https://%{HTTP_HOST}e%{REQUEST_URI}e; rel="canonical"" env=IS_CANONICAL
更新:完整的.htaccess
在这里:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
RewriteCond %{QUERY_STRING}e ^print=pdf&redirect=false$
RewriteRule ^(.*)$ - [E=IS_CANONICAL:1,L]
Header set Link "https://%{HTTP_HOST}e%{REQUEST_URI}e; rel="canonical"" env=IS_CANONICAL
<IfModule mod_rewrite.c> RewriteEngine On RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] RewriteBase / RewriteRule ^index.php$ - [L] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] </IfModule> RewriteCond %{QUERY_STRING}e ^print=pdf&redirect=false$ RewriteRule ^(.*)$ - [E=IS_CANONICAL:1,L] Header set Link "https://%{HTTP_HOST}e%{REQUEST_URI}e; rel="canonical"" env=IS_CANONICAL
发布的指令有几个问题:
-
设置
IS_CANONICAL
环境变量的mod_rewrite规则位于错误的位置,甚至可能没有为所需的请求进行处理(除非url路径恰好映射到物理资产)。该规则需要在之前重写到您的前端控制器(index.php
)。ie。在整个规则块和<IfModule>
包装器之前。 -
%{QUERY_STRING}e
-RewriteCond
TestString后面的e
匹配文字e
。你正在mod_rewrite指令中使用mod_headers语法。这里应该是%{QUERY_STRING}
,而不是e
。 -
如果您期望接收此查询字符串的URL受到内部重写(即。它不映射到物理资产,并通过你的前端控制器路由),那么你将需要测试
REDIRECT_IS_CANONICAL
在Header
指令,而不是IS_CANONICAL
。这是因为重写引擎在第一次传递期间设置的任何env var都是在处理Header
指令之前通过使用REDIRECT_
前缀来重命名的。(注:这不适用于LiteSpeed服务器。) -
你不应该在设置env变量的规则上使用
L
标志,否则请求将不会通过你的前端控制器路由。
小点:
-
不需要在
RewriteRule
模式中匹配^(.*)$
,因为您只需要规则成功即可。一个简单的^
(string start of anchor)就足够了,而且效率更高。 -
第一个指令块被封装在
<IfModule>
节中,但是设置env变量的规则不是。这是不一致的(并且违背了使用<IfModule>
包装器的初衷)。如果这段代码是您自己的,那么您可能根本不应该在这里使用<IfModule>
包装器。否则,如果这是你的框架的一部分(它看起来像标准的WordPress代码块),那么你应该让它保持原样。
试试下面的命令:
RewriteCond %{QUERY_STRING} ^print=pdf&redirect=false$
RewriteRule ^ - [E=IS_CANONICAL:1]
Header set Link "https://%{HTTP_HOST}e%{REQUEST_URI}e; rel="canonical"" env=REDIRECT_IS_CANONICAL
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /
RewriteRule ^index.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
您不需要在第一条规则之前重复RewriteEngine
指令,因为它已经在文件的后面出现了。(为了可读性,RewriteEngine
指令应该在文件的顶部出现一次。然而,实际上控制整个文件的是该指令的最后一次出现。因此,在第一条规则之前包括一个额外的RewriteEngine
指令实际上并没有做任何事情。
Header
(mod_headers)指令的位置并不重要(它可能出现在文件的末尾)。因为不同的Apache模块是在请求期间的不同时间独立处理的。但是,将它与设置env变量的mod_rewrite规则放在一起是合乎逻辑的。