Converting Mod-rewrite rules which use %(QUERY_STRING) to NGINX rewrite format?

感情迁移 提交于 2019-12-11 00:22:20

问题


I've been stuck the last few days trying to convert the following Apache/Mod_Rewrite rewrite rule to NGINX format. Anyone know where I am going wrong?

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

回答1:


This does not answer the question -- please read the comment with more information I am leaving this answer to host other variants of rewriting viable for other situations.

You can do it easier:

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

The ? suffix tells Nginx to not append original arguments to the new URL.

Sidenote

By the way, if you are doing static mapping of one set of IDs to another, there is a more effective solution:

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 takes the first parameter (topic from query string in this case) and does a lookup through the table. It then assigns the result to the second parameter (new_topic_id). Two benefits:

  • The lookup is very effective, as Nginx creates a hash table.
  • The lookup occurs only when you are going to use new_topic_id (lazy evaluation)



回答2:


From the details you provided I agree the only way is to use if (despite the fact if is not recommended generally). Try this:

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

I shall leave my previous answer as it might be of help for someone else.

Simpler example to make sure this works

I've put a simpler example to show this works. Here it is the Nginx configuration fragment:

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

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

vv.html contents:

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

Now reload Nginx and point your browser to http://hostname/index.html at the first and http://hostname/index.html?topic=11 after that.




回答3:


Seems lots of people are still viewing this question. Hope my answer helps!

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

Tested and it works. A couple of critical but subtle fixes in the rewrite line:

  1. I removed the query string part "?topic=(.+)" from the old url because nginx rewrite rule doesn't match query strings at all(also called args in nginx). It only tries to match PATH. reference link
  2. The argument topic=xxxx is automatically stored in nginx in this variable: $arg_topic. So I can simply put "oldid=$arg_topic" in the new url. reference link
  3. I put a question mark "?" at the end of the new url so that nginx won't try to attach the query string from the old url. By default, nginx will attach the entire query string from the old url.


来源:https://stackoverflow.com/questions/2442374/converting-mod-rewrite-rules-which-use-query-string-to-nginx-rewrite-format

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!