如何将相同的RewriteCond附加到.htaccess中的不同RewriteRule?
当用户代理与 Twitter 或 Facebook 匹配时,我想将 url 重定向到我的 ogp 页面。
我的重定向图像是这样的。
/news/detail.html?id=1 -> /api/v1/informations/ogp/1?lang=ja
/news/detail.html?id=1&lang=en -> /api/v1/informations/ogp/1?lang=en
/sport/detail.html?id=1 -> /api/v1/sports/ogp/1?lang=ja
/sport/detail.html?id=1&lang=en -> /api/v1/sports/ogp/1?lang=en
/event/common/detail.html?id=1 -> /api/v1/events/ogp/1?lang=ja
/event/common/detail.html?id=1 -> /api/v1/events/ogp/1?lang=ja
/event/special/detail.html?id=2&lang=en -> /api/v1/events/ogp/2?lang=en
/event/special/detail.html?id=2 -> /api/v1/events/ogp/2?lang=ja
所以我写了htaccess,Env params工作正常,但是当RewriteRule接管两个或更多时,重写规则不起作用。
<IfModule mod_setenvif.c>
SetEnvIfNoCase User-Agent "^facebookexternalhit.*$" UA_FACEBOOK=1
SetEnvIfNoCase User-Agent "^facebookplatform.*$" UA_FACEBOOK=1
SetEnvIfNoCase User-Agent "^Twitterbot.*$" UA_TWITTER=1
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
RewriteCond %{ENV:UA_TWITTER} ^1$
RewriteCond %{QUERY_STRING} (^|&)id=(\d+)&lang=(\w+)($|&)
RewriteRule ^news/detail.html$ /api/v1/informations/ogp/%2?lang=%3 [R,L]
RewriteRule ^sport/detail.html$ /api/v1/sports/ogp/%2?lang=%3 [R,L]
RewriteRule ^event/common/detail.html$ /api/v1/events/ogp/%2?lang=%3 [R,L]
RewriteRule ^event/special/detail.html$ /api/v1/events/ogp/%2?lang=%3 [R,L]
RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
RewriteCond %{ENV:UA_TWITTER} ^1$
RewriteCond %{QUERY_STRING} (^|&)id=(\d+)($|&)
RewriteRule ^news/detail.html$ /api/v1/informations/ogp/%2?lang=ja [R,L]
RewriteRule ^sport/detail.html$ /api/v1/sports/ogp/%2?lang=ja [R,L]
RewriteRule ^event/common/detail.html$ /api/v1/events/ogp/%2?lang=ja [R,L]
RewriteRule ^event/special/detail.html$ /api/v1/events/ogp/%2?lang=ja [R,L]
</IfModule>
我想用相同的 RewriteCond 重定向它们,该怎么做?
即使是肮脏的代码也是受欢迎的!
I want to redirect url to my ogp page when User-agent matches Twitter or Facebook.
My redirect image is like this.
/news/detail.html?id=1 -> /api/v1/informations/ogp/1?lang=ja
/news/detail.html?id=1&lang=en -> /api/v1/informations/ogp/1?lang=en
/sport/detail.html?id=1 -> /api/v1/sports/ogp/1?lang=ja
/sport/detail.html?id=1&lang=en -> /api/v1/sports/ogp/1?lang=en
/event/common/detail.html?id=1 -> /api/v1/events/ogp/1?lang=ja
/event/common/detail.html?id=1 -> /api/v1/events/ogp/1?lang=ja
/event/special/detail.html?id=2&lang=en -> /api/v1/events/ogp/2?lang=en
/event/special/detail.html?id=2 -> /api/v1/events/ogp/2?lang=ja
So I wrote htaccess, Env params work ok, but rewrite rule does not work when RewriteRule takes two or more over.
<IfModule mod_setenvif.c>
SetEnvIfNoCase User-Agent "^facebookexternalhit.*quot; UA_FACEBOOK=1
SetEnvIfNoCase User-Agent "^facebookplatform.*quot; UA_FACEBOOK=1
SetEnvIfNoCase User-Agent "^Twitterbot.*quot; UA_TWITTER=1
</IfModule>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
RewriteCond %{ENV:UA_TWITTER} ^1$
RewriteCond %{QUERY_STRING} (^|&)id=(\d+)&lang=(\w+)($|&)
RewriteRule ^news/detail.html$ /api/v1/informations/ogp/%2?lang=%3 [R,L]
RewriteRule ^sport/detail.html$ /api/v1/sports/ogp/%2?lang=%3 [R,L]
RewriteRule ^event/common/detail.html$ /api/v1/events/ogp/%2?lang=%3 [R,L]
RewriteRule ^event/special/detail.html$ /api/v1/events/ogp/%2?lang=%3 [R,L]
RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
RewriteCond %{ENV:UA_TWITTER} ^1$
RewriteCond %{QUERY_STRING} (^|&)id=(\d+)($|&)
RewriteRule ^news/detail.html$ /api/v1/informations/ogp/%2?lang=ja [R,L]
RewriteRule ^sport/detail.html$ /api/v1/sports/ogp/%2?lang=ja [R,L]
RewriteRule ^event/common/detail.html$ /api/v1/events/ogp/%2?lang=ja [R,L]
RewriteRule ^event/special/detail.html$ /api/v1/events/ogp/%2?lang=ja [R,L]
</IfModule>
I want to redirect them all with same RewriteCond, how to do that?
Even dirty code is welcome!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这实际上只有 4 个 URL 映射(当省略
lang
参数时,它会分配一个默认值 - 目标保持不变),因此您只需要 4 个规则(如果您提取lang
代码> 参数)。最后 2 个重定向到同一目标,以便可以轻松组合它们(使用正则表达式替换(common|special)
),只留下 3 个单独的所需规则。您可以这样做以避免任何重复:
这里的技巧是使用
S
(skip
) 标志来跳过以下 3 个规则,当用户代理不是 Facebook 或 Twitter(或者不存在id
URL 参数) - 反转逻辑。这意味着仅当用户代理是 Facebook 或 Twitter 并且存在id
URL 参数时,才会处理最后 3 条规则。请注意,我使用非捕获子模式来确保反向引用(即
%1
)仅引用我们感兴趣的组。注意:我将
RewriteBase
更改为“简化”最后 3 条规则。不过,如果您有其他指令,那么您可能想将其改回来。您当前的规则将无法在
指令 (Apache 2.4) 内匹配,因为在这个上下文中RewriteRule
指令匹配绝对文件路径,而不是相对 URL 路径(可能是因为
容器被合并非常< /em> 晚了)。如果不存在冲突,这里的一个简单解决方法是从
RewriteRule
模式的开头删除字符串开头锚点 (^
) em> 以便能够匹配/absolute/file/path/to/public_html/news/detail.php
形式的文件路径。 (尽管我可能会添加斜杠前缀以避免任何部分路径段匹配。)因此,您可以像这样编写它,而不是使用
表达式:This is really only 4 URL mappings (when the
lang
param is omitted it assigned a default - the target remains the same), so you only need 4 rules (if you extract thelang
param). And the last 2 redirect to the same target so these can be easily combined (using regex alternation(common|special)
), leaving just 3 separate rules that are required.You could do it like this to avoid any repetition:
The trick here is the use of the
S
(skip
) flag to skip over the following 3 rules when the User-Agent is not Facebook or Twitter (or there is noid
URL param present) - reversing the logic. Which means that the last 3 rules are only processed when the User-Agent is Facebook or Twitter and theid
URL param is present.Note that I used non-capturing subpatterns to ensure that the backreferences (ie.
%1
) only refer to the group we are interested in.NB: I changed the
RewriteBase
to "simplify" the last 3 rules. Although if you have other directives then you may want to change this back.Your current rules would have failed to match inside an
<If>
directive (Apache 2.4), because in this context theRewriteRule
directive matches against the absolute file-path, not a relative URL-path (probably because<If>
containers are merged very late).Providing there are no conflicts, a simple workaround here is to just remove the start-of-string anchor (
^
) from the start of theRewriteRule
pattern so as to be able to match a file-path of the form/absolute/file/path/to/public_html/news/detail.php
. (Although I would probably add a slash prefix in order to avoid any partial path-segment matches.)So, you could potentially write it like this instead using an
<If>
expression:这段肮脏的代码做了我想要它做的事情。
我尝试了使用 If 指令的方法,但它不适用于我的环境变量,如下面的代码,
所以我通过一次又一次编写大量相同的 RewriteCond 解决了这个问题。
如果你有更好的写法,我欢迎。
This dirty code did what I wanted it to do.
I tried the method of using the If directive, but it didn't work with my environment variable like below code
so I solved this problem by writing a lot of same RewriteCond again and again.
If you have a better way to write this, I welcome it.