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.*$" 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>
I want to redirect them all with same RewriteCond, how to do that?
Even dirty code is welcome!
2
Answers
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.
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: