views:

638

answers:

2

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

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)
Alexander Azarov
HipHop-opatamus
A: 

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.

Alexander Azarov
Thanks for the recommendation - just tried it, still doesn't work. It just stays on index.php, which makes me think the "if ($arg_topc != "") is not working?
HipHop-opatamus
I've created a simple demo for you.
Alexander Azarov