2

I'm using Docker to run nginx on macOS to serve static files on http://localhost:8080.

When clicking on an anchor link, the port is being lost.

For example, clicking on <a href="/foo"> will link to http://localhost/foo instead of http://localhost:8080/foo.

My nginx config is:

server {
  listen               80 default_server;

  server_name          _;

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

  location ~ /\. {
    deny all;
  }

  location ~* /(?:uploads|files)/.*\.php$ {
    deny all;
  }

  error_page 404 /404.html;

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

  location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
  }
}

The directory structure of /var/www/root is:

├── foo
│   └── index.html
├── bar
│   └── index.html
└── baz
    └── index.html

However, when changing:

try_files $uri $uri/ $uri.html =404;

to:

try_files $uri/index.html $uri $uri/ $uri.html =404;

the anchor links link correctly.

However, the following does not work:

try_files $uri/ $uri $uri.html =404;

What is going on exactly? Is there a way to exclude $uri/index.html from try_files and have the anchor links preserve the port?

Update

This works, but I'm not quite sure why.

if (-d $request_filename) {
  rewrite [^/]$ $scheme://$http_host$uri/ permanent;
}

location / {
  try_files $uri $uri/ $uri.html =404;
}
Community
  • 1
  • 1
Raphael Rafatpanah
  • 19,082
  • 25
  • 92
  • 158
  • 1
    Did you see this one? https://stackoverflow.com/questions/39519136/prevent-nginx-to-remove-the-port - I've had plenty of trouble here, but the other way. Leaving the port on when I don't want it. – dmgig May 08 '18 at 14:51
  • @dgig, I had not seen it, but their solution works for me as well. – Raphael Rafatpanah May 08 '18 at 14:56
  • oh great then. glad it worked. – dmgig May 08 '18 at 14:57
  • 1
    @dgig, Now to find out why ;-) – Raphael Rafatpanah May 08 '18 at 14:58
  • When I've tested various options that others reported to be successful, it first wasn't working. I had to clear the cache of the site (e.g. by using Developer Tools -> Network -> [x] Disable Cache) to finally see the successful redirect. – Leon Nov 24 '22 at 00:25

1 Answers1

1

I can't see the Dockerfile but I'm assuming you run the container with a port mapping of 8080:80. However, nginx is probably still sending the Host header with port 80 and the anchor tag uses that host given how the base URI is calculated:

User agents must calculate the base URI according to the following precedences (highest priority to lowest):

  1. The base URI is set by the BASE element.
  2. The base URI is given by meta data discovered during a protocol interaction, such as an HTTP header (see [RFC2616]).
  3. By default, the base URI is that of the current document. Not all HTML documents have a base URI (e.g., a valid HTML document may appear in an email and may not be designated by a URI). Such HTML documents are considered erroneous if they contain relative URIs and rely on a default base URI.

Reference: https://www.w3.org/TR/html401/struct/links.html#edef-BASE


For development, it sounds like running the container with 8080:8080 should work. For production you might wanna set the appropriate server_name or Host header via an envvar.

Community
  • 1
  • 1
Maroshii
  • 3,937
  • 4
  • 23
  • 29
  • Your assumption of `8080:80` was correct. That makes perfect sense now. Changing to `8080:8080` works nicely with: `try_files $uri $uri/ $uri.html =404;` (after changing the `listen` directive as well). Thank you! – Raphael Rafatpanah May 08 '18 at 15:27