diff --git a/lib/context.js b/lib/context.js index 1b92f018c..9d57b7ebe 100644 --- a/lib/context.js +++ b/lib/context.js @@ -195,6 +195,7 @@ delegate(proto, 'response') .method('set') .method('append') .method('flushHeaders') + .method('back') .access('status') .access('message') .access('body') diff --git a/lib/response.js b/lib/response.js index 371875fe1..fc355e61e 100644 --- a/lib/response.js +++ b/lib/response.js @@ -19,6 +19,7 @@ const extname = require('path').extname; const vary = require('vary'); const only = require('only'); const util = require('util'); +const deprecate = require('depd')('koa'); /** * Prototype. @@ -259,7 +260,11 @@ module.exports = { redirect(url, alt) { // location - if ('back' == url) url = this.ctx.get('Referrer') || alt || '/'; + if ('back' == url) { + deprecate('Special-cased string "back" through redirect will be removed in v3, ' + + 'consider migrating usage to ctx.back() instead.'); + url = this.ctx.get('Referrer') || alt || '/'; + } this.set('Location', url); // status @@ -278,6 +283,24 @@ module.exports = { this.body = `Redirecting to ${url}.`; }, + /** + * Perform a special-cased "back" to provide Referrer support. + * When Referrer is not present, `alt` or "/" is used. + * + * Examples: + * + * ctx.back() + * ctx.back('/index.html') + * + * @param {String} [alt] + * @api public + */ + + back(alt) { + const url = this.ctx.get('Referrer') || alt || '/'; + this.redirect(url); + }, + /** * Set Content-Disposition header to "attachment" with optional `filename`. * diff --git a/test/response/back.js b/test/response/back.js new file mode 100644 index 000000000..e6c30c378 --- /dev/null +++ b/test/response/back.js @@ -0,0 +1,33 @@ + +'use strict'; + +const assert = require('assert'); +const context = require('../helpers/context'); + +describe('ctx.back([alt])', () => { + it('should redirect to Referrer', () => { + const ctx = context(); + ctx.req.headers.referrer = '/login'; + ctx.back(); + assert.equal(ctx.response.header.location, '/login'); + }); + + it('should redirect to Referer', () => { + const ctx = context(); + ctx.req.headers.referer = '/login'; + ctx.back(); + assert.equal(ctx.response.header.location, '/login'); + }); + + it('should default to alt', () => { + const ctx = context(); + ctx.back('/index.html'); + assert.equal(ctx.response.header.location, '/index.html'); + }); + + it('should default redirect to /', () => { + const ctx = context(); + ctx.back(); + assert.equal(ctx.response.header.location, '/'); + }); +});