Score:2

How to rewrite URL using NGINX to hide index.php inside multiple subfolders that change frequently?

bm flag

So we have a PHP development server where each dev has a personal subdomain like https://dev-abc.mysite.com with a corresponding NGINX config.

Devs check out a branch of our repo into folders like this:

  • /var/www/html/dev-abc/branch-X
  • /var/www/html/dev-abc/branch-Y
  • /var/www/html/dev-abc/branch-Z

URL pattern:
https://dev-abc.mysite.com/{BRANCH}/index.php/{MODULE}/{CLASS}/?event={EVENT}&otherParamX=Y

{MODULE} is a folder in modules/
{CLASS} is a class file in modules/{MODULE}
{EVENT} is a method inside a class inside modules/{MODULE}

Branches are accessed like so: https://dev-abc.mysite.com/branch-X/index.php/report/invoice

We are simply trying to rewrite the URL to:
https://dev-abc.mysite.com/branch-X/report/invoice/

For all subdirectories under their subdomain.

The NGINX configs look like this:

Path:
/etc/nginx/conf.d/dev-abc.conf

server {
        server_tokens off;

        listen 80;
        autoindex off;
        server_name dev-abc.mysite.com;
        root /var/www/html/dev-a;

        error_log /home/dev-abc/nginx-error.log notice;

        include /etc/nginx/includes/dev_sandbox;

        rewrite_log on;
}

Note: /etc/nginx/includes/dev_sandbox includes a lot of stuff for headers and CORS so I won't post it unless it's needed because it's long.

I have tried the following:

Attempt 1:

location / {
    try_files $uri $uri/ /index.php$is_args$args;
}

NGINX throws: ^(.+.php)(/.+)" does not match "/index.php" Also getting "File not found" in the browser

Attempt 2:

location ~(.+)/(.+) {
    try_files $uri $1/index.php/$2;
}

Works:
https://dev-abc.mysite.com/branch-X/report/

Does not work:
https://dev-abc.mysite.com/branch-X/report/invoice/

Attempt 3:

location ~(.+)/(.+)/(.+) {
    try_files $uri $1/control.php/$2/$3;
}

Works:
https://dev-abc.mysite.com/branch-X/report/invoice/

Does not work:
https://dev-abc.mysite.com/branch-X/report/

Throws:
"/var/www/html/dev-abc/branch-X/report/index.php" is not found

Score:1
jp flag

Repetition operators like * and + are greedy. So the first capture in (.+)/(.+) takes everything until the last / (with at least one character following it). So the behaviour of your Attempt 2 is entirely expected.

You can use the lazy repetition operators instead, like *? and +?, for example:

location ~ (.+?)/(.+) { ... }

Or you can use a character class that matches only characters which are not / (remembering that the first character is always a /), for example:

location ~ (/[^/]+)/(.+) { ... }

Although not strictly necessary in this case, but you should probably add anchors around the expression as you are only interested in matching the entire URI, for example:

location ~ ^(.+?)/(.+)$ { ... }

Or:

location ~ ^(/[^/]+)/(.+)$ { ... }

Important Note

Regular expression location blocks are evaluated in order until a match is found. Make sure that your location ^(.+.php)(/.+) block appears first in the order, to avoid a redirection loop.

WeaponX86 avatar
bm flag
Thank you for the reply. I tried this but same result as attempt #2 above ` location ~ ^(/[^/]+)/(.+)$ { try_files $uri $1/index.php/$2/$3; }` Works: https://dev-abc.mysite.com/branch-X/report/ Does not work: https://dev-abc.mysite.com/branch-X/report/invoice/
Score:0
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.