From f9f7714e9528cb02f61ae7d8c8da09b502f88d69 Mon Sep 17 00:00:00 2001 From: Martin Iwanowski Date: Mon, 21 Oct 2024 01:41:19 +0200 Subject: [PATCH] response.redirect: extract special-cased back, fixes #904 (#1115) The simple solution to drop special-cased `'back'` in `response.redirect`. I can't label but should be labeled as version-major. This PR **does not** make use of Symbol as purposed in #904. **Edit** If this solution is acceptable, a deprecation should be added to Koa 2 on `'back'` use. --------- Co-authored-by: Kevin Peno --- __tests__/response/back.js | 32 ++++++++++++++++++++++++++++++++ lib/context.js | 1 + lib/response.js | 25 ++++++++++++++++++++++++- 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 __tests__/response/back.js diff --git a/__tests__/response/back.js b/__tests__/response/back.js new file mode 100644 index 000000000..cd28fd94f --- /dev/null +++ b/__tests__/response/back.js @@ -0,0 +1,32 @@ +'use strict' + +const assert = require('assert') +const context = require('../../test-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, '/') + }) +}) diff --git a/lib/context.js b/lib/context.js index fafe1ec51..7cd06bef4 100644 --- a/lib/context.js +++ b/lib/context.js @@ -204,6 +204,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 8893fcba5..5cda6ce60 100644 --- a/lib/response.js +++ b/lib/response.js @@ -18,6 +18,7 @@ const only = require('./only.js') const util = require('util') const encodeUrl = require('encodeurl') const Stream = require('stream') +const deprecate = require('depd')('koa') /** * Prototype. @@ -293,7 +294,11 @@ module.exports = { redirect (url, alt) { // location - if (url === 'back') url = this.ctx.get('Referrer') || alt || '/' + if (url === 'back') { + 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 || '/' + } if (/^https?:\/\//i.test(url)) { // formatting url again avoid security escapes url = new URL(url).toString() @@ -316,6 +321,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`. *