1.0.0 • Published 3 years ago

clean-redirect v1.0.0

Weekly downloads
3
License
MIT
Repository
github
Last release
3 years ago

npm NPM codecov Maintainability

When it comes to redirects, it's easy to end up with a redirect chain. First your server forces HTTPS. Redirects to the naked domain. Then removes the trailing slash. And only then does the request hit your backend, where it is met with redirects dependent on your business logic. Clean Redirect is a middleware for Express that helps you avoid redirect chains by keeping all of the redirect rules in one place, redirecting only once they've all been applied.

While it may be desirable to keep some of those redirects (such as force HTTPS) on the web server, there are cases when they need to happen on the backend, such as when hosting an application on Heroku or similar infrastructure.

:zap:   Features

  • Enforce HTTPS.
  • Redirect from naked domain to WWW and vice versa.
  • Remove trailing slash from path.
  • Convert path to lowercase.
  • The ability to pass in a function with your own business logic.
  • A lot of configurable options to keep it as simple or governed as you need it.

:floppy_disk:   Installation

Using NPM:

npm install --save clean-redirect

Using Yarn:

yarn add clean-redirect

:mag:   Example

const express = require('express');
const cleanRedirect = require('clean-redirect');

const app = express();

const getCustomRedirectLocation = (req, res, redirector) => {
  if (redirector.path === '/store') {
    redirector
      .setPath('/marketplace')
      .setPersistQueryString(false)
      .setRedirectCode(302);
  }
};

const redirector = cleanRedirect({
  forceHttps: true,
  toWww: true,
  pathToLowerCase: true,
  removeTrailingSlash: true,
  persistQueryString: true,
  customRedirects: getCustomRedirectLocation,
  callNextOnRedirect: true,
  redirectCode: 301,
});

app.use(redirector);

// http://yourapp.com/SUBSCRIBE/?email=johndoe@gmail.com => 301
// https://www.yourapp.com/subscribe?email=johndoe@gmail.com

// http://yourapp.com/STORE/?showBundles=true => 302
// https://www.yourapp.com/marketplace

:space_invader:   Usage

Clean Redirect exposes a single middleware function that accepts multiple options, some of which are used to configure the redirect logic, others which are used to govern the behavior of the middleware.

Options

OptionTypeRequiredDescription
forceHttpsBooleanNoRedirects non-secure HTTP requests to HTTPS. Defaults to false.
toWwwBooleanNoRedirects requests to the naked (root) domain to the WWW domain. Defaults to false. Both toWww and toNaked cannot set to true at the same time.
toNakedBooleanNoRedirects requests to the WWW domain to the naked (root) domain. Defaults to false. Both toWww and toNaked cannot set to true at the same time.
pathToLowerCaseBooleanNoRedirects requests with capital letters in the path to the same path, but lowercase. Defaults to false.
removeTrailingSlashBooleanNoRedirects requests with a trailing slash to the same path, without a slash. Defaults to false.
persistQueryStringBooleanNoWhen set, the query string from the original request will be persisted to the redirect location. Defaults to false (default behavior for Express).
redirectCodeIntegerNoSets the redirect code to be used by default. Valid values are 301 and 302. Defaults to 302.
callNextOnRedirectBooleanNoWhen set to true, the next() function will be called in the middleware after the redirect has taken place. Defaults to false.
deferRedirectToNextBooleanNoWhen set to true, res.redirect() is not called in the middleware. Instead, an instance of CleanRedirect is saved to res.locals and available for further governance in the middleware that follows.
customRedirectsFunctionNoThis is a function that accepts three arguments (req, res, redirector) and is called before calling res.redirect(). Pass this in to include custom redirect logic using conditions and setters and getters for the CleanRedirect object (see below).

Ideally, this middleware should come before any other redirect-related logic, globally, using the app.use() method. However, you can also pass different configurations into different areas of your application.

Methods for CleanRedirect

There are two cases in which there is direct access to the object (an instance of CleanRedirect) that stores all the original and target URL data:

  • Within the function passed to the customRedirects option.
  • In later middleware, through the res.locals.cleanRedirect property, when passing a value of true to deferRedirectToNext.

In these situations, there are getters and setters available to further modify the configuration of the redirect and values of the target URL which will be passed into the res.redirect() method.

Getter Methods

NameTypeDescription
protocolStringGet the target protocol.
hostnameStringGet the target hostname.
pathStringGet the target path.
queryStringStringGet the target queryString.
hashStringGet the target hash.
requiresRedirectBooleanCompares the original URL data and the mutated values to decide if a redirect is needed or not.
redirectUrlStringReturns the full string that will be passed into the res.redirect() method.
redirectCodeIntegerGet the configured redirect code (301 or 302).

Setter Methods

All setter methods return this and are thus chainable.

MethodDescription
setProtocol(string)Set the target protocol.
setHostname(string)Set the target hostname.
setPath(string)Set the target path.
setQueryString(string)Set the target queryString.
setHash(string)Set the target hash.
setPersistQueryString(boolean)Set the option to persist the query string on the target URL.
setRedirectCode(integer)Set the redirect code to be passed into the res.redirect() method.
setPathOverride(string)Set an explicit value for the path passed into the res.redirect() method. Can be utilized to use the path relative and back redirects supported by Express. When set, all target URL data will be ignored, and the value passed as an override will be directly passed into res.redirect().

:fire:   Acknowledgements

Alexey Chernyshov (@ft502 on Dribbble) - For such a beautiful logo!

:black_nib:   Author

Ray East (@raycharius) - Technical Product Manager by Day, NodeJS Developer by Night