mirror of
https://github.com/zebrajr/express.git
synced 2025-12-06 00:19:48 +01:00
Add "escape json" setting for res.json and res.jsonp
closes #3268 closes #3269
This commit is contained in:
parent
628438d8d8
commit
7154014785
|
|
@ -1,6 +1,7 @@
|
|||
unreleased
|
||||
==========
|
||||
|
||||
* Add `"json escape"` setting for `res.json` and `res.jsonp`
|
||||
* Improve error message when autoloading invalid view engine
|
||||
* Improve error messages when non-function provided as middleware
|
||||
* Skip `Buffer` encoding when not generating ETag for small response
|
||||
|
|
|
|||
|
|
@ -254,9 +254,10 @@ res.json = function json(obj) {
|
|||
|
||||
// settings
|
||||
var app = this.app;
|
||||
var escape = app.get('json escape')
|
||||
var replacer = app.get('json replacer');
|
||||
var spaces = app.get('json spaces');
|
||||
var body = stringify(val, replacer, spaces);
|
||||
var body = stringify(val, replacer, spaces, escape)
|
||||
|
||||
// content-type
|
||||
if (!this.get('Content-Type')) {
|
||||
|
|
@ -296,9 +297,10 @@ res.jsonp = function jsonp(obj) {
|
|||
|
||||
// settings
|
||||
var app = this.app;
|
||||
var escape = app.get('json escape')
|
||||
var replacer = app.get('json replacer');
|
||||
var spaces = app.get('json spaces');
|
||||
var body = stringify(val, replacer, spaces);
|
||||
var body = stringify(val, replacer, spaces, escape)
|
||||
var callback = this.req.query[app.get('jsonp callback name')];
|
||||
|
||||
// content-type
|
||||
|
|
@ -1098,14 +1100,38 @@ function sendfile(res, file, options, callback) {
|
|||
}
|
||||
|
||||
/**
|
||||
* Stringify JSON, like JSON.stringify, but v8 optimized.
|
||||
* Stringify JSON, like JSON.stringify, but v8 optimized, with the
|
||||
* ability to escape characters that can trigger HTML sniffing.
|
||||
*
|
||||
* @param {*} value
|
||||
* @param {function} replaces
|
||||
* @param {number} spaces
|
||||
* @param {boolean} escape
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
|
||||
function stringify(value, replacer, spaces) {
|
||||
function stringify (value, replacer, spaces, escape) {
|
||||
// v8 checks arguments.length for optimizing simple call
|
||||
// https://bugs.chromium.org/p/v8/issues/detail?id=4730
|
||||
return replacer || spaces
|
||||
var json = replacer || spaces
|
||||
? JSON.stringify(value, replacer, spaces)
|
||||
: JSON.stringify(value);
|
||||
|
||||
if (escape) {
|
||||
json = json.replace(/[<>&]/g, function (c) {
|
||||
switch (c.charCodeAt(0)) {
|
||||
case 0x3c:
|
||||
return '\\u003c'
|
||||
case 0x3e:
|
||||
return '\\u003e'
|
||||
case 0x26:
|
||||
return '\\u0026'
|
||||
default:
|
||||
return c
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return json
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,28 @@ describe('res', function(){
|
|||
})
|
||||
})
|
||||
|
||||
describe('"json escape" setting', function () {
|
||||
it('should be undefined by default', function () {
|
||||
var app = express()
|
||||
assert.strictEqual(app.get('json escape'), undefined)
|
||||
})
|
||||
|
||||
it('should unicode escape HTML-sniffing characters', function (done) {
|
||||
var app = express()
|
||||
|
||||
app.enable('json escape')
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.json({ '&': '<script>' })
|
||||
})
|
||||
|
||||
request(app)
|
||||
.get('/')
|
||||
.expect('Content-Type', 'application/json; charset=utf-8')
|
||||
.expect(200, '{"\\u0026":"\\u003cscript\\u003e"}', done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"json replacer" setting', function(){
|
||||
it('should be passed to JSON.stringify()', function(done){
|
||||
var app = express();
|
||||
|
|
|
|||
|
|
@ -242,6 +242,28 @@ describe('res', function(){
|
|||
})
|
||||
})
|
||||
|
||||
describe('"json escape" setting', function () {
|
||||
it('should be undefined by default', function () {
|
||||
var app = express()
|
||||
assert.strictEqual(app.get('json escape'), undefined)
|
||||
})
|
||||
|
||||
it('should unicode escape HTML-sniffing characters', function (done) {
|
||||
var app = express()
|
||||
|
||||
app.enable('json escape')
|
||||
|
||||
app.use(function (req, res) {
|
||||
res.jsonp({ '&': '\u2028<script>\u2029' })
|
||||
})
|
||||
|
||||
request(app)
|
||||
.get('/?callback=foo')
|
||||
.expect('Content-Type', 'text/javascript; charset=utf-8')
|
||||
.expect(200, /foo\({"\\u0026":"\\u2028\\u003cscript\\u003e\\u2029"}\)/, done)
|
||||
})
|
||||
})
|
||||
|
||||
describe('"json replacer" setting', function(){
|
||||
it('should be passed to JSON.stringify()', function(done){
|
||||
var app = express();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user