0

I am struggling with some Nginx rewrits for url arguments passed to index.php:

  • Old: ?topic=10126.msg36887
  • New: ?posts/36887/

My two questions:

1) How do I rewrite to the new argument structure since it uses "parameter/value/" rather than the traditional "parameter=value" structure?

2) My "if" statement isn't triggering, and I can't figure out why... The test url domain.com/forum/index.php?topic=10126.msg36887 should redirect to /success, but it isn't rewritten at all.

Here's my current Nginx config:

location /forum/ {
    index index.php index.html index.htm;
    try_files $uri $uri/ /forum/index.php?$uri&$args;

    location /forum/index.php {

        # I know Nginx 'If is Evil', but it's the only way 
        # to trigger rewrites on url parameters
        if ($arg_topic ~ [0-9]+\.\bmsg([0-9]+) {

            # testing whether 'if' triggers:
            rewrite ^ /success? redirect;

            # full rewrite:
            # rewrite ^\/forum\/index\.php ^\/forum\/index\.php\?posts\/$1\/? redirect;

            }
        }
    }

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_pass    127.0.0.1:9000;
    fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include         fastcgi_params;
    }
3
  • /forum/index.php is processed by location ~ \.php$.
    – Alexey Ten
    Dec 18, 2014 at 12:06
  • 1
    It would be much easier to do this redirect in PHP
    – Alexey Ten
    Dec 18, 2014 at 12:07
  • Unfortunately, in this particular situation, redirecting within PHP isn't possible--pretty much has to be at the Nginx level... worst case I can do something like this gist.github.com/jrom/1760790 and test for "if filename is /forum/index.php and if using this old argument value, then rewrite"... I was hoping for a simpler solution though... that would solve my second question, but not my first... any ideas on the first? Dec 18, 2014 at 12:19

2 Answers 2

3

Putting this in the server config block should work: the regexp should match what you need correctly and by stashing the required ID in a variable you can use it later in the rewrite.

Assuming that you won't have a 'topic' argument in other parts of the site, there's really no need to scope this in a location - even if you do, you can alter the first part of the rewrite to match /forum/index.php only.

if ($arg_topic ~ [0-9]+\.msg([0-9]+)$) {
  set $postid $1;
  rewrite ^ /forum/index.php?posts/$postid? last;
}
1
  • if is devil, map is good
    – Ilja
    May 29, 2015 at 0:53
1

If it's only about 'topic' argument this might work:

On 'http' level of your nginx.conf declare following 'map':

map $arg_topic $topic_id {
    "~^\d+\.msg(?<id>\d+)" $id;
    default 0;
}

On 'server' level add appropriate 'location':

location = /forum/index.php {

            #if ($topic_id = 0) {
            #      return 403;
            #}

            include fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_param QUERY_STRING posts/$topic_id/;
            fastcgi_pass 127.0.0.1:9000;
}

Ensure that you have specified 'root' directive on server level so that 'SCRIPT_FILENAME' filled with correct value.

Also you may check whether '$topic_id' is zero (eg. topic_id= is missing or have incorrect value).

Using this your '$_GET' array will contain something like:

array(1) {
  ["posts/36887/"]=>
  string(0) ""
}
2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .