【问题标题】:Converting Mod-rewrite rules which use %(QUERY_STRING) to NGINX rewrite format?将使用 %(QUERY_STRING) 的 Mod 重写规则转换为 NGINX 重写格式?
【发布时间】:2011-01-27 09:28:35
【问题描述】:

过去几天我一直在尝试将以下 Apache/Mod_Rewrite 重写规则转换为 NGINX 格式。有人知道我哪里出错了吗?

MOD_REWRITE:

RewriteCond %{QUERY_STRING} topic=([0-9]+)
RewriteRule /forum/index\.php /forum/vbseo301.php?action=thread&oldid=%1 [L]

NGINX:

location /forum/index.php {
           if ($args ~ "topic=([0-9]+)"){
                        rewrite ^/forum/index\.php?topic=(.+)$ /forum/vbseo301.php?action=thread&oldid=$1 last;
                        }
        }

【问题讨论】:

    标签: .htaccess mod-rewrite url-rewriting nginx


    【解决方案1】:

    这并不能回答问题——请阅读评论以获取更多信息我将留下这个答案,以便在其他情况下提供其他可行的重写变体。

    你可以做的更简单:

    # At "server" level, NOT in "location"
    rewrite ^/forum/index.php
             /forum/vbseo301.php?action=thread&oldid=$arg_topic?
            last;
    

    那个?后缀告诉 Nginx 不要将原始参数附加到新 URL。

    旁注

    顺便说一句,如果您正在将一组 ID 静态映射到另一组,有一个更有效的解决方案:

    http {
      map $arg_topic $new_topic_id {
        default 1;
        2 3;
        4 65;
      }
    
      server {
        # some directives (server_name, listen, etc.) omitted
    
        rewrite ^/forum/index.php /forum/new.php?topic=$new_topic_id? last;
    
        # locations omitted
      }
    }
    

    map 获取第一个参数(在这种情况下,topic 来自查询字符串)并通过表进行查找。然后它将结果分配给第二个参数 (new_topic_id)。两个好处:

    • 查找非常有效,因为 Nginx 创建了一个哈希表。
    • 仅当您要使用 new_topic_id(惰性求值)时才会进行查找

    【讨论】:

    • 感谢您的帮助!我应该提供更多信息,因为我认为这不会 100% 起作用:1)我只希望在查询参数“topic”存在时进行重定向。因此,/forum/index.php?topic=72253 应该重定向到 /forum/vbseo301.php?action=thread&oldid=72253 但根本不应该重定向 /forum/index.php。 2)关于您关于“静态”映射的第二条评论 - 我假设您的意思是我有一个主题 ID 列表,我可以将其包含在 nginx CONF 文件中?不幸的是,我没有,因为有 10,000 多个潜在的主题 ID...
    【解决方案2】:

    根据您提供的详细信息,我同意唯一的方法是使用if(尽管一般不推荐使用if)。试试这个:

    location /forum/index.php {
      if ($arg_topic != "") {
        rewrite ^ /forum/vbseo301.php?action=thread&oldid=$arg_topic? break;
      }
    }
    

    我将留下我之前的答案,因为它可能对其他人有帮助。

    更简单的示例来确保它有效

    我已经举了一个更简单的例子来展示这个作品。这里是 Nginx 配置片段:

    location /index.html {
        if ($arg_topic != '') {
            rewrite ^ /vv.html?t=$arg_topic? break;
        }
        ssi on;
        root /home/alaz;
    }
    
    location /vv.html {
        ssi on;
        root /home/alaz;
    }
    

    index.html 内容:

    <b>index</b>
    <br/>
    topic: <!--#echo var="arg_topic" -->
    

    vv.html 内容:

    <b>vv</b>
    <br/>
    topic: <!--#echo var="arg_topic" -->
    <br/>
    t: <!--#echo var="arg_t" -->
    

    现在重新加载 Nginx 并将浏览器指向http://hostname/index.html,然后指向http://hostname/index.html?topic=11

    【讨论】:

    • 感谢您的推荐 - 刚试了下,还是不行。它只是停留在 index.php 上,这让我觉得“if ($arg_topc != "") 不起作用?
    • 我为你创建了一个简单的演示。
    【解决方案3】:

    似乎很多人仍在查看这个问题。希望我的回答有帮助!

    location /forum/index.php {
      if ($args ~ "topic=([0-9]+)"){
        rewrite ^/forum/index\.php$ /forum/vbseo301.php?action=thread&oldid=$arg_topic? last;
      }
    }
    

    经过测试,它可以工作。重写行中的几个关键但微妙的修复:

    1. 我从旧 url 中删除了查询字符串部分“?topic=(.+)”,因为 nginx 重写规则根本不匹配查询字符串(在 nginx 中也称为 args)。它只尝试匹配 PATH。 reference link
    2. 参数 topic=xxxx 会自动存储在 nginx 中的这个变量中:$arg_topic。所以我可以简单地将“oldid=$arg_topic”放在新的网址中。 reference link
    3. 我打了一个问号“?”在新 url 的末尾,这样 nginx 就不会尝试从旧 url 附加查询字符串。默认情况下,nginx 会附加旧 url 中的整个查询字符串。

    【讨论】:

    猜你喜欢
    • 2014-06-30
    • 2016-08-09
    • 2012-02-27
    • 2016-06-18
    • 2018-03-28
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多