0

I've recently switched from apache to nginx. My app is located under /var/www/html and has the following structure:

# tree -a /var/www/html
/var/www/html
├── .htaccess
├── folder1
│   ├── .htaccess
│   └── index.php
├── folder2
│   ├── .htaccess
│   └── index.php
├── index.php
├── file1.php
└── file2.php

.htaccess files in all directories are the same:

# cat /var/www/html/.htaccess 
AddDefaultCharset UTF-8
Options +FollowSymLinks
Options -Indexes
RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(assets)/ - [L,NE]

RewriteRule ^/?$ index.php?param1=main [QSA,L]
RewriteRule ^([-a-zA-Z0-9_]+)/$ index.php?param1=$1 [QSA,L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php?param1=$1&param2=$2 [QSA,L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php?param1=$1&param2=$2&param3=$3 [QSA,L]
RewriteRule ^([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ index.php?param1=$1&param2=$2&param3=$3&param4=$4 [QSA,L]

RewriteRule ^file1.xml$ file1.php [L]
RewriteRule ^file2.xml$ file2.php [L]

ErrorDocument 400 /error/400/
ErrorDocument 401 /error/401/
ErrorDocument 403 /error/403/
ErrorDocument 404 /error/404/
ErrorDocument 500 /error/500/

RedirectMatch (.*)\.inc /error/404/
RedirectMatch (.*)\.tpl /error/404/

Now I am trying to build the nginx config. My goal is to make the following rewrites:

example.com or example.com/ -> example.com/index.php?param1=main
example.com/anything or example.com/anything/ -> example.com/index.php?param1=anything
example.com/anything/else or example.com/anything/else/ -> example.com/index.php?param1=anything&param2=else
etc...

And the same for folder1 and folder2

example.com/folder1 or example.com/folder1/ -> example.com/folder1/index.php?param1=main
example.com/folder1/anything or example.com/folder1/anything/ -> example.com/folder1/index.php?param1=anything
etc...

Nginx config currently looks like:

server {
    listen 443 ssl;
    server_name example.com;
    charset utf-8;

    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;

    root /var/www/html;
        index index.html index.htm index.php;

    location / {
    try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
} 

I used online converter and placed rules under location / { but that did not work. Url like example.com/anything shows 404 and example.com/anything/ tries to download file

2
  • Please add your nginx configuration file you work with and be more specific in describing what "that did not work" actually means. Commented Feb 4, 2021 at 8:21
  • @arkascha uploaded Commented Feb 4, 2021 at 8:26

1 Answer 1

1

There is more than one way to do this. But the following example uses a named location to collect together all of the rewrite rules.

location / {
    try_files $uri $uri/ @rewrite;
}
location @rewrite {
    rewrite ^/$ /index.php?param1=main? last;
    rewrite ^/([-a-zA-Z0-9_]+)/$ /index.php?param1=$1? last;
    rewrite ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ /index.php?param1=$1&param2=$2? last;
    rewrite ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ /index.php?param1=$1&param2=$2&param3=$3? last;
    rewrite ^/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/([A-Za-z0-9-]+)/$ /index.php?param1=$1&param2=$2&param3=$3&param4=$4? last;

    rewrite ^/file1.xml$ /file1.php last;
    rewrite ^/file2.xml$ /file2.php last;
    return 404;
}

All Nginx URIs begin with a leading /. I am assuming that the default action is to return 404 if none of the rules match. The trailing ? prevents any original parameters being appended to the rewritten URI, if you want the original parameters appended, remove the trailing ?. See this document for details.

Note: In your question you state that you want to accept example.com/anything/else or example.com/anything/else/. This is not what the existing .htaccess does. To make the trailing / optional, add a ? after the final / before the $. For example:

rewrite ^/([-a-zA-Z0-9_]+)/?$ /index.php?param1=$1? last;

You can repeat this pattern for other folders, but it will look very messy. This logic belongs inside index.php, but an Nginx example is given below:

location /folder1 {
    try_files $uri $uri/ @rewrite1;
}
location @rewrite1 {
    rewrite ^/folder1/?$ /folder1/index.php?param1=main? last;
    rewrite ^/folder1/([-a-zA-Z0-9_]+)/$ /folder1/index.php?param1=$1? last;
    ...
}

Notice that the regular expression and the rewritten URI both need to include the folder name.

Sign up to request clarification or add additional context in comments.

4 Comments

Thank you, that perfectly worked for the root folder. I tried to add the same way for the folder1 and folder2 like location /folder1 { try_files $uri $uri/ @rewrite; } location @rewrite_folder1 { rewrite ^/$ /index.php?param1=main? last; rewrite ^/([-a-zA-Z0-9_]+)/$ /index.php?param1=$1? last; ... return 404; } But it returns 500 error for requests like example.com/folder1/anything
If you want to expand your question use the Edit button. But you have not shown the contents of the .htaccess file from folder1.
Thank you. .htaccess files in all directories are the same
Added more description. Generally I have 3 locations: /, /folder1 and /folder2 For all locations rewrites are equal and difference is only in url: example.com, example.com/folder1 and example.com/folder2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.