Handling redirects with Express

By

Learn how to redirect server-side in Express with the res.redirect() method, returning a 302 by default or 301, and redirecting to absolute or relative paths.

~~~

Redirects are common in Web Development. You can create a redirect using the Response.redirect() method:

res.redirect('/go-there')

This creates a 302 redirect.

Under the hood, Express sets the Location response header to the URL you passed, along with the status code. The browser receives the response and immediately requests the new URL.

A 302 tells the browser the move is temporary. Search engines keep the old URL in their index. It’s the right choice when you send someone to a login page, or to a “thank you” page after a form submission.

A 301 redirect is permanent, and is made in this way:

res.redirect(301, '/go-there')

Use it when a page moved for good, for example after renaming a URL. Browsers cache 301 responses aggressively, so make sure the new URL is really final. Undoing a 301 that’s already cached in your visitors’ browsers is painful.

If you’re unsure whether you want a 301, 302, 307 or 308, I built a free HTTP status codes lookup that explains when to use each one.

Where can you redirect to?

You can specify an absolute path (/go-there), an absolute url (https://anothersite.com), a relative path (go-there) or use the .. to go back one level:

res.redirect('../go-there')
res.redirect('..')

A relative path is resolved against the URL of the current request. If the user is on /users/settings and you redirect to avatar, they end up on /users/avatar.

You can also redirect back to the Referer HTTP header value (defaulting to / if not set) using

res.redirect('back')

Note that Express 5 removed this 'back' shortcut. There you read the header yourself, keeping the same fallback:

res.redirect(req.get('Referrer') || '/')

The handler keeps running after a redirect

Here’s a pitfall that bites everyone at least once. res.redirect() sends the response, but it does not stop your function. The code after it still runs:

app.get('/dashboard', (req, res) => {
  if (!req.session.user) {
    res.redirect('/login')
  }
  res.render('dashboard')
  //Error: Cannot set headers after they are sent to the client
})

The fix is to return when you redirect:

app.get('/dashboard', (req, res) => {
  if (!req.session.user) {
    return res.redirect('/login')
  }
  res.render('dashboard')
})

The return value is ignored by Express. We only use return to exit the handler early.

~~~

Related posts about express: