Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cascade index.php in nginx "try_files"

In Apache it is possible to redirect everything to the closest index.php, using .htaccess

Example folder structure:

/Subdir
/index.php
/.htaccess   

/Subdir
/Subdir/.htaccess
/Subdir/index.php

If I access /something it will redirect to the root index.php, and if I access /Subdir/something it will redirect to Subdir/index.php

Can this be done in nginx as well? It should be possible, because in nginx documentation it says If you need .htaccess, you’re probably doing it wrong :)

I know how to redirect everything to the root index.php:

location / {
  try_files $uri $uri/ /index.php?$query_string;
}

But how to check for index.php in every parent directory until / ?

edit:

I found that these rules do what I want:

location / {
  try_files $uri $uri/ /index.php?$query_string;
}

location /Subdir{
  try_files $uri $uri/ /Subdir/index.php?$query_string;
}

But is there a way to make it abstract, like

location /$anyfolder{
  try_files $uri $uri/ /$anyfolder/index.php?$query_string;
} 

?

like image 878
nice ass Avatar asked Sep 04 '18 09:09

nice ass


1 Answers

The index directive should take care of most of that

server {
    index index.php;
    ...
} 

If your setup dictates using try_files, then this should work for you:

location / {
    try_files $uri $uri/ $uri/index.php?$query_string =404;
}

You can also capture the location and use as a variable:

location ~ ^/(?<anyfolder>) {
    # Variable $anyfolder is now available
    try_files $uri $uri/ /$anyfolder/index.php?$query_string =404;
}

Edit

I see from your comment that you want to try the subject folder's index.php file first and go on to the one in the root folder if there isn't one in the subject folder.

For that, you could try something like...

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

Note: $is_args$args is better than ?$query_string if there is a chance there might not be arguments.

Edit 2

Okay. Got the bounty but kept on feeling I was missing something and that your query was not actually addressed. After reading and rereading, I now think I finally fully understand your query.

You want to check for index.php in the target folder. If found, this will be executed. If not found, keep checking parent folders up the directory tree until one is found (which may be the root folder).

The answer I gave in "EDIT" above just jumps to the root folder but you will like to check intervening folders first.

Not tested but you could try a recursive regex pattern

# This will recursively swap the parent folder for "current"
# However will only work up to "/directChildOfRoot/grandChildOfRoot"
# So we will add another location block to continue to handle "direct child of root" and "root" folders
location ~ ^/(?<parent>.+)/(?<current>[^\/]+)/? {
    try_files /$current /$current/ /$current/index.php$is_args$args /$parent;
}

# This handles "direct child of root" and "root" folders
location / {
    try_files $uri $uri/ $uri/index.php$is_args$args /index.php$is_args$args;
}
like image 75
Dayo Avatar answered Nov 02 '22 11:11

Dayo