如何在.htaccess中将相同的重写条件附加到不同的重写规则?

hpxqektj  于 2023-03-13  发布在  其他
关注(0)|答案(2)|浏览(117)

当用户代理匹配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参数工作正常,但是当重写规则占用两个或更多时,重写规则不工作。

<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重定向它们,怎么做?
即使是脏代码也是受欢迎的!

vwkv1x7d

vwkv1x7d1#

/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

这实际上只有4个URLMap(当lang参数被省略时,它会分配一个默认值-目标保持不变),所以你只需要4个规则(如果你提取lang参数)。最后2个重定向到同一个目标,这样就可以很容易地将它们组合起来(使用regex交替(common|special)),只剩下3个单独的规则是必需的。
你可以这样做,以避免任何重复:

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]

这里的技巧是使用Sskip)标记,当用户代理 * 不是 * Facebook或Twitter(或者没有id URL参数)时跳过以下3个规则-反转逻辑。这意味着只有当用户代理 * 是 * Facebook或Twitter并且id URL参数存在时,才处理最后3个规则。
注意,我使用了非捕获子模式来确保反向引用(即%1)只引用我们感兴趣的组。
NB:我修改了RewriteBase来“简化”最后3个规则。尽管如果你有其他的指令,那么你可能想把这个改回来。
我试过使用If指令的方法,但不起作用
您当前的规则可能无法在<If>指令(Apache 2.4)中进行匹配,因为在这个 * 上下文 * 中,RewriteRule指令匹配的是绝对文件路径,而不是相对URL路径(可能是因为<If>容器合并得 * 非常 * 晚)。
假设没有冲突,这里的一个简单的解决方法是从RewriteRulepattern 的开头删除字符串开头锚(^),以便能够匹配/absolute/file/path/to/public_html/news/detail.php的文件路径(尽管我可能会添加一个斜杠前缀,以避免任何部分路径段匹配)。
因此,您可以使用<If>表达式来编写它,如下所示:

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>
jmo0nnb3

jmo0nnb32#

这个肮脏的代码做了我想让它做的事情。

<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>

我尝试了使用If指令的方法,但是它不适用于我的环境变量,如下面的代码所示

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

所以我通过一次又一次地编写大量相同的RewriteCond来解决这个问题。
如果你有更好的写作方式,我欢迎。

相关问题