diff --git a/lib/response.js b/lib/response.js index e5865f220..6d1d11e76 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 encodeUrl = require('encodeurl'); /** * Prototype. @@ -260,7 +261,7 @@ module.exports = { redirect(url, alt) { // location if ('back' == url) url = this.ctx.get('Referrer') || alt || '/'; - this.set('Location', url); + this.set('Location', encodeUrl(url)); // status if (!statuses.redirect[this.status]) this.status = 302; diff --git a/package.json b/package.json index 3e0754125..224eeeb96 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "delegates": "^1.0.0", "depd": "^1.1.2", "destroy": "^1.0.4", + "encodeurl": "^1.0.2", "error-inject": "^1.0.0", "escape-html": "^1.0.3", "fresh": "~0.5.2", diff --git a/test/response/redirect.js b/test/response/redirect.js index 619300fbc..e9a29ac63 100644 --- a/test/response/redirect.js +++ b/test/response/redirect.js @@ -2,7 +2,9 @@ 'use strict'; const assert = require('assert'); +const request = require('supertest'); const context = require('../helpers/context'); +const Koa = require('../..'); describe('ctx.redirect(url)', () => { it('should redirect to the given url', () => { @@ -12,6 +14,23 @@ describe('ctx.redirect(url)', () => { assert.equal(ctx.status, 302); }); + it('should auto fix not encode url', done => { + const app = new Koa(); + + app.use(ctx => { + ctx.redirect('http://google.com/😓'); + }); + + request(app.callback()) + .get('/') + .end((err, res) => { + if (err) return done(err); + assert.equal(res.status, 302); + assert.equal(res.headers.location, 'http://google.com/%F0%9F%98%93'); + done(); + }); + }); + describe('with "back"', () => { it('should redirect to Referrer', () => { const ctx = context();