Have nginx redirect everything to https except one directory

I need nginx to redirect all http URLs to https, with the exception a ".secret/" directory which should continue to be served as http.

So, for example:

  • http://example.com/a.html --> https://example.com/a.html
  • http://example.org/z/b.html --> https://example.org/z/b.html
  • http://example.com/.secret/x.html --> http://example.com/.secret/x.html

I have the following in my configuration but for http, it returns addresses that include "_".

server {
    listen 80;
 
    server_name _;
 
    location /.secret {
        return http://$server_name$request_uri;
    }
 
    location / {
        return 301 https://$server_name$request_uri;
    }
}

What am I doing wrong?

UPDATE:

Combining the comments from @mforsetti and @Pothi_Kalimuthu, the following worked:

server {
    listen 80;
 
    server_name _;
 
    location /.secret { }
 
    location / {
        return 301 https://$host$request_uri;
    }
}

Solution 1:

it returns addresses that include "_".

server_name _;

location /.secret {
   return http://$server_name$request_uri;
}

$server_name returns assigned server_name to the server block, which in your case is _; hence the _ in returned address.

If you want it to return a hostname or your Host request header, try using $host, something like:

location /.secret {
    return http://$host$request_uri;
}

.secret/ directory which should continue to be served as http

if you want to serve a directory, specify a root directory.

location /.secret {
    root /path/to/your/parent/of/secret/directory;
}