nginx redirect that forces update of URL in the browser

Dan Dascalescu asked:

I have a very basic nginx setup that redirects www.example.com to example.com, following the best practice. It works, and in the Tor Firefox browser, going to http://www.idorecall.com/blog indeed updates the URL in the address bar to http://idorecall.com/blog.

But this doesn’t change the URL in the address bar of Chrome, Firefox Portable, IE and Opera Portable.

Here’s the modified default nginx config. There are no other nginx config files other than nginx.conf.

server {
  server_name www.idorecall.com;
  return 301 $scheme://idorecall.com$request_uri;
}

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

    root /var/www/html;

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

    server_name idorecall.com;

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

    location /blog {
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header HOST $http_host;

        proxy_pass http://127.0.0.1:2368;
    }
}

wget -S, http://www.rexswain.com/httpview.html, browsershots etc. correctly detect the 301 “Moved permanently” redirect. Most browsers though preserve the www URL. Super frustrating. Firefox and Opera were installed from scratch, so there’s no history hit of the www domain.

GitHub manages to redirect http(s)://www.github.com to https://github.com in every browser. How do they do this?

My answer:


You aren’t seeing the redirect (and krisFR is) because you have IPv6 (and he does not), and your nginx server block containing the redirect is only being used for IPv4 connections.

When a server block omits the listen directive, it defaults to listen *:80, which listens only on all IPv4 addresses (and is equivalent to listen 80). Thus this server block will never be used for IPv6 connections, which fall through to your defined default_server.

To resolve the problem, add the appropriate listen directives to listen on both IPv4 and IPv6.

server {
  listen 80;
  listen [::]:80;
  server_name www.idorecall.com;
  return 301 $scheme://idorecall.com$request_uri;
}

View the full question and answer on Server Fault.

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