@nuxtjs/redirect-module
Advanced tools
Comparing version
@@ -5,2 +5,7 @@ # Change Log | ||
<a name="0.3.0"></a> | ||
# [0.3.0](https://github.com/nuxt-community/redirect-module/compare/v0.2.1...v0.3.0) (2019-08-26) | ||
<a name="0.2.0"></a> | ||
@@ -7,0 +12,0 @@ # [0.2.0](https://github.com/nuxt-community/redirect-module/compare/v0.1.0...v0.2.0) (2018-11-24) |
@@ -1,12 +0,18 @@ | ||
/* eslint-disable no-console */ | ||
// Creates new middleware using provided options | ||
function create(rules) { | ||
return async function redirectRoute(req, res, next) { | ||
const decodedBaseUrl = decodeURI(req.url) | ||
const foundRule = rules.find(o => o.from.test(decodedBaseUrl)) | ||
module.exports = function (options) { | ||
return async function redirectRoute (req, res, next) { | ||
let decodedBaseUrl | ||
try { | ||
decodedBaseUrl = options.onDecode(req, res, next) | ||
} catch (error) { | ||
return options.onDecodeError(error, req, res, next) | ||
} | ||
const foundRule = options.rules.find(o => o.from.test(decodedBaseUrl)) | ||
if (!foundRule) { | ||
return next() | ||
} | ||
// Expect rule 'to' to either a | ||
@@ -17,12 +23,23 @@ // 1) regex | ||
const toTarget = typeof foundRule.to === 'function' ? await foundRule.to(foundRule.from, req) : foundRule.to | ||
let toTarget | ||
try { | ||
toTarget = typeof foundRule.to === 'function' ? await foundRule.to(foundRule.from, req) : foundRule.to | ||
} catch (error) { | ||
return next(error) | ||
} | ||
const toUrl = decodedBaseUrl.replace(foundRule.from, toTarget) | ||
res.statusCode = foundRule.statusCode || 302 | ||
res.setHeader('Location', toUrl) | ||
try { | ||
res.setHeader('Location', toUrl) | ||
} catch (error) { | ||
// Not passing the error as it's caused by URL that was user-provided so we | ||
// can't do anything about the error. | ||
return next() | ||
} | ||
res.statusCode = foundRule.statusCode || options.statusCode | ||
res.end() | ||
} | ||
} | ||
module.exports = create |
@@ -1,16 +0,46 @@ | ||
export default async function nuxtRedirect(moduleOptions) { | ||
if (typeof moduleOptions === 'function') { | ||
moduleOptions = await moduleOptions() | ||
async function redirectModule (moduleOptions) { | ||
const defaults = { | ||
rules: [], | ||
onDecode: (req, res, next) => decodeURI(req.url), | ||
onDecodeError: (error, req, res, next) => next(error), | ||
statusCode: 302 | ||
} | ||
if (typeof this.options.redirect === 'function') { | ||
this.options.redirect = await this.options.redirect() | ||
const options = { | ||
...defaults, | ||
...await parseOptions(this.options.redirect), | ||
...await parseOptions(moduleOptions) | ||
} | ||
const initialRules = Object.assign([], this.options.redirect, moduleOptions) | ||
options.rules = options.rules.map(rule => ({ ...rule, from: new RegExp(rule.from) })) | ||
// Transform each "from" value to a RegExp for later test | ||
const regExpRules = initialRules.map(o => Object.assign(o, { from: new RegExp(o.from) })) | ||
const middleware = require('./middleware.js')(regExpRules) | ||
const middleware = require('./middleware.js')(options) | ||
this.addServerMiddleware(middleware) | ||
} | ||
async function parseOptions (options) { | ||
if (typeof options === 'function') { | ||
options = await options() | ||
} | ||
if (Object.keys(options).length === 0) { | ||
return [] | ||
} | ||
if (Array.isArray(options)) { | ||
return { rules: options } | ||
} | ||
if (typeof options.rules === 'function') { | ||
options.rules = await options.rules() | ||
} | ||
if (options.rules && !Array.isArray(options.rules)) { | ||
options.rules = [options.rules] | ||
} | ||
return options | ||
} | ||
module.exports = redirectModule | ||
module.exports.meta = require('../package.json') |
{ | ||
"name": "@nuxtjs/redirect-module", | ||
"version": "0.2.0", | ||
"description": "", | ||
"version": "0.3.0", | ||
"description": "Nuxt module to dynamically redirect initial requests", | ||
"keywords": [ | ||
"nuxtjs", | ||
"nuxt", | ||
"redirect", | ||
"seo" | ||
], | ||
"license": "MIT", | ||
"contributors": [ | ||
{ | ||
"name": "Alexander Lichter <npm@lichter.io>" | ||
} | ||
"Alexander Lichter <npm@lichter.io>" | ||
], | ||
@@ -19,56 +23,27 @@ "main": "lib/module.js", | ||
"lint": "eslint lib test", | ||
"commitlint": "commitlint -e $GIT_PARAMS", | ||
"test": "yarn lint && jest", | ||
"release": "standard-version && git push --follow-tags && npm publish" | ||
"release": "yarn test && standard-version && git push --follow-tags && npm publish" | ||
}, | ||
"eslintIgnore": [ | ||
"lib/templates/*.*" | ||
], | ||
"files": [ | ||
"lib" | ||
], | ||
"keywords": [ | ||
"nuxtjs", | ||
"nuxt", | ||
"redirect", | ||
"seo" | ||
], | ||
"engines": { | ||
"node": ">=8.0.0", | ||
"npm": ">=5.0.0" | ||
}, | ||
"jest": { | ||
"testEnvironment": "node", | ||
"collectCoverage": true, | ||
"coveragePathIgnorePatterns": [ | ||
"/node_modules/", | ||
"/test/fixture" | ||
] | ||
}, | ||
"devDependencies": { | ||
"@commitlint/cli": "^7.2.1", | ||
"@commitlint/config-conventional": "^7.1.2", | ||
"@nuxtjs/eslint-config": "^0.0.1", | ||
"babel-eslint": "^10.0.1", | ||
"codecov": "^3.1.0", | ||
"eslint": "^5.9.0", | ||
"eslint-config-standard": "^12.0.0", | ||
"eslint-plugin-import": "^2.14.0", | ||
"eslint-plugin-jest": "^22.0.0", | ||
"eslint-plugin-node": "^8.0.0", | ||
"eslint-plugin-promise": "^4.0.1", | ||
"eslint-plugin-standard": "^4.0.0", | ||
"eslint-plugin-vue": "^4.7.1", | ||
"husky": "^1.2.0", | ||
"jest": "^23.6.0", | ||
"jsdom": "^13.0.0", | ||
"nuxt": "^2.3.2", | ||
"standard-version": "^4.4.0" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "npm run lint", | ||
"commit-msg": "npm run commitlint" | ||
} | ||
"@babel/core": "^7.5.5", | ||
"@babel/preset-env": "^7.5.5", | ||
"@commitlint/cli": "^8.1.0", | ||
"@commitlint/config-conventional": "^8.1.0", | ||
"@nuxtjs/eslint-config": "^1.1.2", | ||
"babel-eslint": "^10.0.3", | ||
"babel-jest": "^24.9.0", | ||
"codecov": "^3.5.0", | ||
"consola": "^2.10.1", | ||
"eslint": "^6.2.2", | ||
"get-port": "^5.0.0", | ||
"husky": "^3.0.4", | ||
"jest": "^24.9.0", | ||
"nuxt-edge": "^2.10.0-26112969.c14bb35a", | ||
"request": "latest", | ||
"request-promise-native": "^1.0.7", | ||
"standard-version": "^7.0.0" | ||
} | ||
} |
118
README.md
# Redirect Module 🔀 No more **cumbersome** redirects! | ||
[](https://npmjs.com/package/@nuxtjs/redirect-module) | ||
[](https://npmjs.com/package/@nuxtjs/redirect-module) | ||
[](https://circleci.com/gh/nuxt-community/redirect-module) | ||
[](https://codecov.io/gh/nuxt-community/redirect-module) | ||
[](https://david-dm.org/nuxt-community/redirect-module) | ||
[](http://standardjs.com) | ||
> | ||
[![npm version][npm-version-src]][npm-version-href] | ||
[![npm downloads][npm-downloads-src]][npm-downloads-href] | ||
[![Circle CI][circle-ci-src]][circle-ci-href] | ||
[![Codecov][codecov-src]][codecov-href] | ||
[![Dependencies][david-dm-src]][david-dm-href] | ||
[![Standard JS][standard-js-src]][standard-js-href] | ||
> Nuxt module to dynamically redirect initial requests | ||
[📖 **Release Notes**](./CHANGELOG.md) | ||
@@ -19,19 +20,20 @@ | ||
With the Redirect Module setting up redirects will become easier than ever before! | ||
## Setup | ||
- Add `@nuxtjs/redirect-module` dependency using yarn or npm to your project | ||
- Add `@nuxtjs/redirect-module` to `modules` section of `nuxt.config.js` | ||
- Configure it: | ||
### Inline options | ||
1. Add the `@nuxtjs/redirect-module` dependency with `yarn` or `npm` to your project | ||
2. Add `@nuxtjs/redirect-module` to the `modules` section of `nuxt.config.js`: | ||
3. Configure it: | ||
```js | ||
{ | ||
modules: [ | ||
['@nuxtjs/redirect-module', [ /* Redirect option here */]], | ||
] | ||
['@nuxtjs/redirect-module', { | ||
// Redirect option here | ||
}] | ||
] | ||
} | ||
``` | ||
### Dedicated option array | ||
### Using top level options | ||
```js | ||
@@ -41,9 +43,35 @@ { | ||
'@nuxtjs/redirect-module' | ||
], | ||
redirect: [ | ||
// Redirect options here | ||
] | ||
], | ||
redirect: [ | ||
// Redirect options here | ||
] | ||
} | ||
``` | ||
## Options | ||
### `rules` | ||
- Default: `[]` | ||
Rules of your redirects. | ||
### `onDecode` | ||
- Default: `(req, res, next) => decodeURI(req.url)` | ||
You can set decode. | ||
### `onDecodeError` | ||
- Default: `(error, req, res, next) => next(error)` | ||
You can set callback when there is an error in the decode. | ||
### `statusCode` | ||
- Default: `302` | ||
You can set the default statusCode which gets used when no statusCode is defined on the rule itself. | ||
## Usage | ||
@@ -56,3 +84,3 @@ | ||
{ from: '^/myoldurl', to: '/mynewurl' } | ||
] | ||
] | ||
``` | ||
@@ -65,3 +93,3 @@ | ||
{ from: '^/myoldurl', to: '/mynewurl', statusCode: 301 } | ||
] | ||
] | ||
``` | ||
@@ -74,8 +102,8 @@ | ||
redirect: [ | ||
{ from: '^/myoldurl/(.*)$', to: '/comeallhere', } // Many urls to one | ||
{ from: '^/anotherold/(.*)$', to: '/new/$1', } // One to one mapping | ||
] | ||
{ from: '^/myoldurl/(.*)$', to: '/comeallhere' }, // Many urls to one | ||
{ from: '^/anotherold/(.*)$', to: '/new/$1' } // One to one mapping | ||
] | ||
``` | ||
Furthermoer you can use a function to create your `to` url as well :+1: | ||
Furthermore you can use a function to create your `to` url as well :+1: | ||
The `from` rule and the `req` of the middleware will be provided as arguments. | ||
@@ -106,10 +134,28 @@ The function can also be *async*! | ||
Now, if you want to customize your redirects, how your decode is done | ||
or when there is some error in the decode, you can also: | ||
```js | ||
redirect: { | ||
rules: [ | ||
{ from: '^/myoldurl', to: '/mynewurl' } | ||
], | ||
onDecode: (req, res, next) => decodeURI(req.url), | ||
onDecodeError: (error, req, res, next) => next(error) | ||
} | ||
``` | ||
**ATTENTION**: The factory function **must** return an array with redirect | ||
objects (as seen above). | ||
## Gotchas | ||
The redirect module will not work in combination with `nuxt generate`. | ||
Redirects are realized through a server middleware, which can only react when there is a server running. | ||
## Development | ||
- Clone this repository | ||
- Install dependencies using `yarn install` or `npm install` | ||
- Start development server using `npm run dev` | ||
1. Clone this repository | ||
2. Install dependencies using `yarn install` or `npm install` | ||
3. Start development server using `npm run dev` | ||
@@ -121,1 +167,15 @@ ## License | ||
Copyright (c) Alexander Lichter <npm@lichter.io> | ||
<!-- Badges --> | ||
[npm-version-src]: https://img.shields.io/npm/dt/@nuxtjs/redirect-module.svg?style=flat-square | ||
[npm-version-href]: https://npmjs.com/package/@nuxtjs/redirect-module | ||
[npm-downloads-src]: https://img.shields.io/npm/v/@nuxtjs/redirect-module/latest.svg?style=flat-square | ||
[npm-downloads-href]: https://npmjs.com/package/@nuxtjs/redirect-module | ||
[circle-ci-src]: https://img.shields.io/circleci/project/github/nuxt-community/redirect-module.svg?style=flat-square | ||
[circle-ci-href]: https://circleci.com/gh/nuxt-community/redirect-module | ||
[codecov-src]: https://img.shields.io/codecov/c/github/nuxt-community/redirect-module.svg?style=flat-square | ||
[codecov-href]: https://codecov.io/gh/nuxt-community/redirect-module | ||
[david-dm-src]: https://david-dm.org/nuxt-community/redirect-module/status.svg?style=flat-square | ||
[david-dm-href]: https://david-dm.org/nuxt-community/redirect-module | ||
[standard-js-src]: https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square | ||
[standard-js-href]: https://standardjs.com |
10282
22%17
-5.56%71
108.82%175
52.17%