From c24200c48d1d995048aca6ecbae5976f45c70c24 Mon Sep 17 00:00:00 2001 From: Krishna Pandey Date: Wed, 1 Apr 2026 11:56:42 +0530 Subject: [PATCH] fix(res.set): remove implicit mime lookup and charset injection for Content-Type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, res.set('Content-Type', value) silently called mime.contentType() on the value, which would: - perform a mime-type lookup if the value contained no '/' (e.g. 'html' → 'text/html; charset=utf-8') - append a charset if none was present (e.g. 'text/plain' → 'text/plain; charset=utf-8') This hidden mutation was unexpected: res.set is a generic header setter and should not transform user input. res.type() already exists as the dedicated API for mime-lookup + charset behaviour, and callers that want it should use that method explicitly. Changes: - Remove the Content-Type special-case block from res.set/res.header - res.json now explicitly sets 'application/json; charset=utf-8' so its behaviour is unchanged without relying on the removed magic - Update tests to reflect the new pass-through semantics of res.set Fixes: #7034 --- lib/response.js | 10 +--------- test/res.send.js | 4 ++-- test/res.set.js | 17 +++++++++-------- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/lib/response.js b/lib/response.js index f965e539dd2..2bfc1026df9 100644 --- a/lib/response.js +++ b/lib/response.js @@ -239,7 +239,7 @@ res.json = function json(obj) { // content-type if (!this.get('Content-Type')) { - this.set('Content-Type', 'application/json'); + this.set('Content-Type', 'application/json; charset=utf-8'); } return this.send(body); @@ -668,14 +668,6 @@ res.header = function header(field, val) { ? val.map(String) : String(val); - // add charset to content-type - if (field.toLowerCase() === 'content-type') { - if (Array.isArray(value)) { - throw new TypeError('Content-Type cannot be set to an Array'); - } - value = mime.contentType(value) - } - this.setHeader(field, value); } else { for (var key in field) { diff --git a/test/res.send.js b/test/res.send.js index 8547b77648b..803fb7ed2b2 100644 --- a/test/res.send.js +++ b/test/res.send.js @@ -174,7 +174,7 @@ describe('res', function(){ request(app) .get('/') - .expect('Content-Type', 'text/plain; charset=utf-8') + .expect('Content-Type', 'text/plain') .expect(200, 'hey', done); }) @@ -187,7 +187,7 @@ describe('res', function(){ request(app) .get("/") - .expect("Content-Type", "text/plain; charset=utf-8") + .expect("Content-Type", "text/plain") .expect(200, "hey", done); }) diff --git a/test/res.set.js b/test/res.set.js index 04511c1c95f..89f17afcc85 100644 --- a/test/res.set.js +++ b/test/res.set.js @@ -61,31 +61,32 @@ describe('res', function(){ .expect(200, '["123","456"]', done); }) - it('should not set a charset of one is already set', function (done) { + it('should set Content-Type without mime lookup', function (done) { var app = express(); app.use(function (req, res) { - res.set('Content-Type', 'text/html; charset=lol'); + res.set('Content-Type', 'text/html'); res.end(); }); request(app) .get('/') - .expect('Content-Type', 'text/html; charset=lol') + .expect('Content-Type', 'text/html') .expect(200, done); }) - it('should throw when Content-Type is an array', function (done) { - var app = express() + it('should not perform mime lookup for extension-like values', function (done) { + var app = express(); app.use(function (req, res) { - res.set('Content-Type', ['text/html']) - res.end() + res.set('Content-Type', 'html'); + res.end(); }); request(app) .get('/') - .expect(500, /TypeError: Content-Type cannot be set to an Array/, done) + .expect('Content-Type', 'html') + .expect(200, done); }) })