☄ Redirect non-www to www in a meteor app deployed on Galaxy with SSL

in JavaScript, Meteor

You cannot have both www and non-www version because they would be considered two different sites. I root for the www version. See the yes-www arguments for this. Without https, the redirection is super easy to setup; you use URL forwarding at the DNS level. But with https this is not possible. Let’s see how to fix that.

Why doesn’t it work with a basic URL record?

Almost every DNS manager offers as URL record type that allow you to make redirections like going from http://mydomain.com to http://www.myotherdomain.net. But this is actually not a real DNS record type. They add a hidden record that makes http://mydomain.com to point on a hidden server they own and this server operate a 301 redirection to http://www.myotherdomain.net.

This is super convenient and works great over http, but not over https. Because to accept a redirection like that from the hidden server, your browser requires this hidden server to be able to negotiate the SSL connection. Which means it need to have your SSL certificate and your private key. And you cannot give that since it would defeat the entire purpose of SSL.

The global idea

We have four urls :

And we want the first three to point to the last one. We need to setup things in Galaxy (the hosting platform), DNSimple (the DNS manager) and in our server code.

☄ Galaxy side

Of course, you need an application all setup. But if you are there, this is probably the case. If you deployed with a script like this one: DEPLOY_HOSTNAME=galaxy.meteor.com meteor deploy --owner=yourTeamName --settings=settings.json www.mydomain.com. You have to go to the settings panel: https://galaxy.meteor.com/app/www.mydomain.com/settings.

Under “DOMAIN & ENCRYPTION”, you have to expand www.mydomain.com, enable the https certificate with let’s encrypt ; and check “Always use HTTP….”.

Then you click on “Add new domain” and you add mydomain.com. This will allow you to get the requests to the naked domain. Enable https and force with “Always”.

This will redirect all requests to https.

📡 DNS manager side (the example of DNSimple)

I like the way DNSimple works. The interface is super efficient and they offer all the functionalities I look for. But most DNS managers and registars will be able to do the same thing. So go in your domain > DNS > Manage records.

You need to setup two records with “Add record”:

Leave it some time to propagate. (If you use Google DNS in your network settings, the propagation is super fast.)

This will direct all www and non www requests to your Galaxy server.

⚙ Server side

In your Meteor application, add this code :

WebApp.rawConnectHandlers.use(
    (req, res, next) => {

        /**
         * Redirect non-www to www in production
         */
        if (
            process.env.NODE_ENV != 'development' &&
            !req.headers.host.includes('www')
        ) {
            res.writeHead(
                301, {
                    'Location': 'https://www.mydomain.com' + req.originalUrl,
                }
            );
            return res.end();
        }

        /**
         * Keep going
         * /!\ DO NOT DELETE /!\
         */
        return next();

    }
);

WebApp.rawConnectHandlers.use means that this hook will the triggered by every requests before Meteor did anything.

At first, we check that we are in production with process.env.NODE_ENV != 'development'. Then if the request does not have www in it, we redirect to the www version.

This will redirect non www to www.

❤ You’re done

Enjoy.