written by Andre Liem
11/01/2017

How to redirect traffic to a preferred domain in NuxtJS with custom server middleware

Are you running a SSR using NuxtJS and need to redirect traffic from the non www domain to www, or vice versa? Learn how easy it is to to achieve this using serverMiddleware.

Introduction

I have been working on a VueJS app that is utilizing SSR with NuxtJS. After some research I ended up sticking with Heroku for hosting my app. This has been great so far as deploying is easy, Heroku has awesome support, and I know that scaling up is something I won't have to worry about down the road. The challenge is that with Heroku, and like many similar services, you can't simply SSH onto the server to reconfigure nginx or apache to redirect/map traffic.

For example, for my site I wanted to redirect the bare domain to the www version. The DNS can redirect traffic, but to the best of my knowledge (warning: I am not a server guy), it is unable to redirect paths or parameters. I actually have a closed ticket on github about this.

mydomain.com to www.mydomain.com [works]

mydomain.com/hello_page to www.mydomain.com/hello_page [fails!]

In the end, I decided what would be simplest is to simply redirect at the app level using NuxtJS itself. My app is already using the redirect-ssl created by Pooya Parsa, so it seemed reasonable that a domain redirect would be easy enough.

Server Middleware vs middleware

First thing is first, if you read the docs on middleware you need to know that there is a difference between server middleware and route middleware.

Don't confuse it (server middleware) with routes middleware which are being called before each route by Vue in Client Side or SSR. serverMiddleware are just running in server side before vue-server-renderer and can be used for server specific tasks like handling API requests or serving assets.

Routes middleware is where you can put common application logic such as authentication checks. Server middleware is where you put logic that is reliant on the HTTP request/response cycle.

It's quite easy to build a custom middleware file. All you need to do is the following

module.exports = {
  serverMiddleware:  [
    '~/redirect-to-www.js'
  ]
}

Then create the file from the root:

touch redirect-to-www.js

redirect-to-www.js

Next, lets look at the general structure of this middleware file.

module.exports = function (req, res, next) {
  return next()
}

The function receives a Http request & response object and next function to continue the chain of requests. NuxtJS relies on the Connect server framework.

You can refer to the NodeJS API docs for details on how to interact with these objects here.

In the above code, all that is happening is it's returning next to carry on request. You could add some console.log in there if you want to see it happening. Refer to the CLI npm output when you refresh the site.

Following this, we want to obtain few key pieces of data.

  • the host domain (are we on the www domain or not?)
  • environment (only run this in production)
  • url (any path or params in the request to pass on)

Here's how we can pull them out:

module.exports = function (req, res, next) {
  const host = req.headers.host
  const url = req.url
  const env = process.env.NODE_ENV
}

With this data, you can build a basic conditional check which will redirect the traffic to the proper domain, in our case the www domain if we're on production and the domain is not already on www.

module.exports = function (req, res, next) {
  const host = req.headers.host
  const url = req.url
  const env = process.env.NODE_ENV
  const canonicalDomain = process.env.CANONICAL_DOMAIN // e.g. www.destination_domain.com

  if (env === 'production' && host !== canonicalDomain) {
    res.writeHead(301, { Location: 'https://' + canonicalDomain + url })
    return res.end()
  }

  return next()
}

So here we are assuming you have defined the desirable domain in the enviroment as CANONICAL_DOMAIN. By canonical, I mean the preferred version as this is the typical meaning in SEO terms for web pages.

If the app is running in production and is not on the canonical domain, add a 301 redirect in the response object with the full path using the canonical domain.

Lastly, don't forget to return the result with res.end().

Conclusion

That wraps up this basic tutorial on how you can easily intercept requests and modify the response using the serverMiddleware property! If you want to look at another example that has a bit more going on, I would check out the redirect-ssl source code.

In the end all you need is some basic knowledge of the NodeJS response request objects and you can do all sorts of filtering/logic before traffic hits the routes.