skip to Main Content

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


  1. Chosen as BEST ANSWER

    This dirty code did what I wanted it to do.

    <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]
    
        RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
        RewriteCond %{ENV:UA_TWITTER} ^1$
        RewriteCond %{QUERY_STRING} (^|&)id=(d+)&lang=(w+)($|&)
        RewriteRule ^sport/detail.html$ /api/v1/sports/ogp/%2?lang=%3 [R,L]
    
        RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
        RewriteCond %{ENV:UA_TWITTER} ^1$
        RewriteCond %{QUERY_STRING} (^|&)id=(d+)&lang=(w+)($|&)
        RewriteRule ^event/common/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+)&lang=(w+)($|&)
        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]
    
        RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
        RewriteCond %{ENV:UA_TWITTER} ^1$
        RewriteCond %{QUERY_STRING} (^|&)id=(d+)($|&)
        RewriteRule ^sport/detail.html$ /api/v1/sports/ogp/%2?lang=ja [R,L]
    
        RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
        RewriteCond %{ENV:UA_TWITTER} ^1$
        RewriteCond %{QUERY_STRING} (^|&)id=(d+)($|&)
        RewriteRule ^event/common/detail.html$ /api/v1/events/ogp/%2?lang=ja [R,L]
    
        RewriteCond %{ENV:UA_FACEBOOK} ^1$ [OR]
        RewriteCond %{ENV:UA_TWITTER} ^1$
        RewriteCond %{QUERY_STRING} (^|&)id=(d+)($|&)
        RewriteRule ^event/special/detail.html$ /api/v1/events/ogp/%2?lang=ja [R,L]
    </IfModule>
    

    I tried the method of using the If directive, but it didn't work with my environment variable like below code

    <If "%{ENV:UA_FACEBOOK} -eq 1 || %{ENV:UA_TWITTER} -eq 1"></If>
    

    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.


  2. /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&lang=en -> /api/v1/events/ogp/1?lang=en
    
    /event/special/detail.html?id=2 -> /api/v1/events/ogp/2?lang=ja
    /event/special/detail.html?id=2&lang=en -> /api/v1/events/ogp/2?lang=en
    

    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 the lang 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:

    RewriteEngine On
    RewriteBase /api/v1
    
    # Get "lang" (default to "ja")
    RewriteRule ^ - [E=LANG:ja]
    RewriteCond %{QUERY_STRING} (?:^|&)lang=(w+)($|&)
    RewriteRule ^ - [E=LANG:%1]
    
    # Get "id" (if any)
    RewriteCond %{QUERY_STRING} (?:^|&)id=(d+)($|&)
    RewriteRule ^ - [E=ID:%1]
    
    # If not Facebook|Twitter OR no ID then skip the next 3 rules
    RewriteCond %{HTTP_USER_AGENT} !^(facebook(externalhit|platform)|twitterbot) [NC,OR]
    RewriteCond %{ENV:ID} ^$
    RewriteRule ^ - [S=3]
    
    # If here then Facebook|Twitter and "id" param are passed, LANG already set
    RewriteRule ^news/detail.html$ informations/ogp/%{ENV:ID}?lang=%{ENV:LANG} [R,L]
    RewriteRule ^sport/detail.html$ sports/ogp/%{ENV:ID}?lang=%{ENV:LANG} [R,L]
    RewriteRule ^event/(common|special)/detail.html$ events/ogp/%{ENV:ID}?lang=%{ENV:LANG} [R,L]
    

    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 no id 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 the id 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.

    I tried the method of using the If directive, but it didn’t work

    Your current rules would have failed to match inside an <If> directive (Apache 2.4), because in this context the RewriteRule 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 the RewriteRule 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:

    RewriteEngine On
    
    # Get "id" (if any)
    RewriteCond %{QUERY_STRING} (?:^|&)id=(d+)($|&)
    RewriteRule ^ - [E=ID:%1]
    
    # Facebook|Twitter AND "id" param are passed
    <If "%{HTTP_USER_AGENT} =~ /^(?i)(facebook(externalhit|platform)|twitterbot)/ && reqenv('ID') =~ /d+/">
        # Get "lang" (default to "ja")
        RewriteRule ^ - [E=LANG:ja]
        RewriteCond %{QUERY_STRING} (?:^|&)lang=(w+)($|&)
        RewriteRule ^ - [E=LANG:%1]
    
        # Redirects
        RewriteRule /news/detail.html$ /api/v1/informations/ogp/%{ENV:ID}?lang=%{ENV:LANG} [R,L]
        RewriteRule /sport/detail.html$ /api/v1/sports/ogp/%{ENV:ID}?lang=%{ENV:LANG} [R,L]
        RewriteRule /event/(common|special)/detail.html$ /api/v1/events/ogp/%{ENV:ID}?lang=%{ENV:LANG} [R,L]
    </If>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search