3

What I want is for the first to be turned into the second..

/widget              => /widget/index.php
/widget/             => /widget/index.php
/widget?act=list     => /widget/index.php?act=list
/widget/?act=list    => /widget/index.php?act=list
/widget/list         => /widget/index.php?act=list
/widget/v2?act=list  => /widget/v2.php?act=list
/widget/v2/?act=list => /widget/v2.php?act=list
/widget/v2/list      => /widget/v2.php?act=list

v2 could also be v45, basically "v\d+"
act, "list" in this case, can have many values and more will be added.
Any additional query parameters would just be passed on with $args, I guess.

Basically URLs not specifying the version will go to index.php, which can then decide what specific version file to include. What I am afraid of happening is loops - this should sit in

location /widget {

right?.

(As for putting the version of the API in the URL, I'm not trying to be RESTful, and target audience is small)

Resources on how to do this entirely in index.php using "routers" also welcome :-/

MSpreij
  • 85
  • 1
  • 9

2 Answers2

3

With three rules you can match the example cases and following versions of the widgets:

rewrite ^\/widget\/(v\d+)\/?(\?act=)?(.*)$ /widget/$1.php?act=$2 last;
rewrite ^\/widget\/?$ /widget/index.php last;
rewrite ^\/widget\/?(\?act=)?(.*) /widget/index.php?act=$2 last;

I have written these using a online regexp tester but did not setup a test environment with Nginx.

The first rule will match all cases with a version number, covering with or without a slash and with or without the ?act argument.

The second rule will cover the basic widget call without any arguments, again with and without trailing slash.

The last rule will cover all non-versioned widget calls, covering with or without a slash and with or without the ?act argument.

Order of there last two rules are important.

Joffrey
  • 2,021
  • 1
  • 12
  • 14
  • aaand I awarded the bounty to the wrong post >.< no idea how /that/ happened, work is making me too tired. Gods of ServerFault, feel free to whatever. – MSpreij Aug 25 '14 at 22:57
  • np, just hope the answer was to your satisfaction :) – Joffrey Aug 26 '14 at 14:23
2
server {
    ...
    rewrite ^/widget$                   /widget/index.php           last;
    rewrite ^/widget/$                  /widget/index.php           last;
    rewrite ^/widget\?act=list$         /widget/index.php?act=list  last;
    rewrite ^/widget/\?act=list$        /widget/index.php?act=list  last;
    rewrite ^/widget/list$              /widget/index.php?act=list  last;
    rewrite ^/widget/v(\d+)\?act=list$  /widget/v$1.php?act=list    last;
    rewrite ^/widget/v(\d+)/\?act=list$ /widget/v$1.php?act=list    last;
    rewrite ^/widget/v(\d+)/list$       /widget/v$1.php?act=list    last;
    ...
    location /widget {
        ...
    }
}

To match the digits you need a capture group (), this is a regex concept.
The capture group is referenced in the rewrite as $1 which means 'backreference 1'

Although I don't know if this is going to be a sustainable list for you.
For instance, instead of capture ?act=list, why not capture everything, and add it back in the rewrite rule like this:

rewrite ^/widget(.*)         /widget/index.php?$1  last;

I'm not 100% sure on how your URLs will look before the rewrite, so I can't give a comprehensive rule for this.

Vasili Syrakis
  • 4,558
  • 3
  • 22
  • 30
  • "Although I don't know if this is going to be a sustainable list for you." Afraid not :-/ There are many values for act, and more will be added, esp in future versions. – MSpreij Aug 22 '14 at 10:27