2

My gatsby site redirects to trailing slash and then redirects again back to non-trailing slash.

nginx config file:

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    include snippets/ssl-example.com.conf;
    include snippets/ssl-params.conf;

    server_name example.com;
    return 301 https://www.$server_name$request_uri;
}

server {
      listen 443 ssl http2;
        listen [::]:443 ssl http2;
        include snippets/ssl-example.com.conf;
        include snippets/ssl-params.conf;

        root /var/www/example.com/html;

        index index.html index.htm index.nginx-debian.html;

        server_name www.example.com;

        location ~ /.well-known {
                allow all;
        }

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }

        location ~* \.(?:html)$ {
          add_header Cache-Control "public, max-age=0, must-revalidate";
        }

        location = /sw.js {
          add_header Cache-Control "public, max-age=0, must-revalidate";
        }

        location /page-data {
          add_header Cache-Control "public, max-age=0, must-revalidate";
        }

        location /static {
          add_header Cache-Control "public, max-age=31536000, immutable";
        }

        location ~* \.(?:js|css)$ {
          add_header Cache-Control "public, max-age=31536000, immutable";
        }

    error_page  404  /404.html;
}

When I open my website with a trailing slash, I see a redirect to the same URL but without a trailing slash:

example.com/hello-world/ -> example.com/hello-world

That's the expected behavior.

But when I open my website without a trailing slash, I see a redirect to a trailing slash, and then a redirect to without a trailing slash again.

example.com/hello-world -> example.com/hello-world/ -> example.com/hello-world

This should not happen. Where did I go wrong in my configuration? Any help is very much appreciated.

mattpr
  • 2,504
  • 19
  • 17
Robin Wieruch
  • 14,900
  • 10
  • 82
  • 107
  • I don't see anything in your config that would make redirecting "expected behaviour". Are there any other nginx conf files in `/etc/nginx/conf.d` or something in `/etc/nginx/nginx.conf` that might cause the redirects? Maybe something in your ssl snippets files? Are you sure it is a server-side `3xx` redirect and not a client-side redirect based on the contents of your `hello-world`? The trailing slash redirect would normally be due to an nginx `rewrite` somewhere which I don't see in your config. – mattpr Nov 16 '21 at 11:50
  • Nothing related to redirections in the other files on my VM. I started my website locally and I can't see this behavior. Locally it just redirects from `hello-world/` to `hello-world` as expected. – Robin Wieruch Nov 16 '21 at 12:25
  • "Locally it just redirects from hello-world/ to hello-world as expected." Why is this expected? I don't see this in your config. – mattpr Nov 16 '21 at 12:36
  • I guess that’s what Gatsby.js is doing on my behalf. – Robin Wieruch Nov 16 '21 at 12:37
  • Yeah okay. I don't see any issue (related to redirects anyway) with your nginx config. I suspect your issue is on the gatsby.js side then. Not enough information in your post to help you. – mattpr Nov 16 '21 at 12:42
  • Thanks @mattpr for pointing me in the right direction. I found this issue https://github.com/gatsbyjs/gatsby/discussions/27889#discussioncomment-254854 regarding Gatsby. Seems like I have to use trailing slashes everywhere. If you want, you can answer the question with this issue regarding Gatsby + give me a hint how I need to rewrite my nginx config for redirecting to trailing slashes instead of no slashes :) Thanks again! – Robin Wieruch Nov 16 '21 at 12:51

1 Answers1

2

nginx

Nginx's behaviour regarding slashes is documented here.

If a location is defined by a prefix string that ends with the slash character, and requests are processed by one of proxy_pass, fastcgi_pass, uwsgi_pass, scgi_pass, memcached_pass, or grpc_pass, then the special processing is performed. In response to a request with URI equal to this string, but without the trailing slash, a permanent redirect with the code 301 will be returned to the requested URI with the slash appended. If this is not desired, an exact match of the URI and location could be defined like this:

location /user/ {
    proxy_pass http://user.example.com; 
}

location = /user {
    proxy_pass http://login.example.com; 
}

This doesn't apply to you because you are not using CGI or upstream app server...you are just serving files (if I understand correctly).

I'm not a gatsby expert but from the link in your comment...

Gatsby works better, smoother, cleaner (etc.) with trailing slashes

There are a variety of nginx configs floating around from people that have used them successful with Gatsby. Here is one for instance.

The most relevant parts for you are...

redirect paths that don't contain . or ? AND don't end with / to the same path but with trailing /.

e.g. redirect /foo/bar to /foo/bar/ but don't mess with /foo/bar.ext or /fo.o/bar or /foo/bar?hello.

rewrite ^([^.\?]*[^/])$ $1/ permanent

try to serve the requested URI interpreting it in the following order of preference:

  • as is (path to file)
  • as a directory
  • as directory containing index.html file
  • finally 404 error if none of the above were valid
try_files $uri $uri/ $uri/index.html =404;

gatsby

From the gatsby issue link you posted they say the following:

Explicitly use the trailing slash in all usages of the <Link> component and/or invocations of navigate()

and

Install gatsby-plugin-force-trailing-slashes. Even though Gatsby generates the static html pages within their own named directories by default, this plugin forces the path value for each page to end in a / - critical for configuring the core Gatsby @reach/router at build time.

and then finally rebuild the gatsby site since some of this config only has impact at build time.

mattpr
  • 2,504
  • 19
  • 17