nginx redirects subdirectory requests without trailing slash to a URL with specified port

Marcel Linke asked:

I have the following problem.

In my local test configuration, when I try to access https://www.testdomain.local/admin it will always redirect me to https://www.testdomain.local:8443/admin/ which cannot be resolved in my system.

My nginx is running inside a Docker container which forwards requests to port 443 to the port 8443 where nginx is listen.

The admin folder is a subdirectory of the root folder.

root -> /application/public/testdomain
root/admin -> /application/public/testdomain/admin

The current behaviour looks like this:

https://www.testdomain.local -> https://www.testdomain.local (correct)
https://www.testdomain.local/ -> https://www.testdomain.local (correct)
https://www.testdomain.local/admin/ (with trailing slash) -> https://www.testdomain.local/admin/ (correct)
https://www.testdomain.local/admin (without trailing slash) -> https://www.testdomain.local:8443/admin/ (incorrect)

For the last case my preferred behaviour would be:

https://www.testdomain.local/admin -> https://www.testdomain.local:8443/admin or https://www.testdomain.local/admin/

I tried many of the solutions I found via Google or ServerFault, but could not get the desired behaviour.

server {
    listen 8443 ssl;

    server_name www.testdomain.local;
    client_max_body_size 108M;

    access_log /var/log/nginx/testdomain.access.log anonymized;

    ssl_certificate /application/common/certificate.crt;
    ssl_certificate_key /application/common/privatekey.key;

    root /application/public/testdomain;
    index index.php;
    if (!-e $request_filename) {
        rewrite ^.*$ /index.php last;
    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PHP_VALUE "error_log=/var/log/nginx/application_php_errors.log";
        fastcgi_buffers 16 16k;
        fastcgi_buffer_size 32k;
        include fastcgi_params;

My answer:

nginx doesn’t know you are actually serving the site on the default port 443, as you told it to listen on a diffferent port. Thus when it creates its own redirects, it adds the nonstandard port number.

You can turn this behavior off with port_in_redirect off;. nginx will then omit the port number in its redirects.

Or, you can turn off absolute redirects with absolute_redirect off; and all redirects will be relative to the URL path root. In this case, nginx will redirect to /admin/ instead of https://www.testdomain.local:8443/admin/.

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.