fix(res.send): add Content-Length header only if Transfer-Encoding is not present (#4893)

* fix(respond): add Content-Length header only if Transfer-Encoding is not present

* fix(response): used get('Transfer-Encoding')

* test(res.send): covered Transfer-Encoding and Content-Length headers logic

* chore(response): removed comment

* chore(res.redirect): revert changes to focus on res.send

* test(res.send): added tests for all transfer encodings

* docs: update History.md to include bug fix for HTTP header conflict in res.send()

---------

Co-authored-by: Sebastian Beltran <[email protected]>
This commit is contained in:
Yury Shkoda
2026-06-15 22:06:31 -05:00
committed by GitHub
co-authored by Sebastian Beltran
parent 0065edc45d
commit 246818a5a3
3 changed files with 36 additions and 3 deletions
+7
View File
@@ -1,5 +1,12 @@
# Unreleased Changes
## 🐞 Bug fixes
- Fixed HTTP header conflict between Content-Length and Transfer-Encoding in res.send - by [@YuryShkoda](https://github.com/YuryShkoda) in [#4893](https://github.com/expressjs/express/pull/4893)
Fixed the behavior of `res.send()` to prevent conflicts between `Content-Length` and `Transfer-Encoding` HTTP headers in responses. The `Content-Length` header in `res.send()` is now only added when a `Transfer-Encoding` header is not present, complying with the HTTP specification that states both headers should not coexist in the same response
## 🚀 Improvements
* Improve HTML structure in `res.redirect()` responses when HTML format is accepted by adding `<!DOCTYPE html>`, `<title>`, and `<body>` tags for better browser compatibility - by [@Bernice55231](https://github.com/Bernice55231) in [#5167](https://github.com/expressjs/express/pull/5167)
+4 -3
View File
@@ -162,9 +162,10 @@ res.send = function send(body) {
var etagFn = app.get('etag fn')
var generateETag = !this.get('ETag') && typeof etagFn === 'function'
// populate Content-Length
var len
if (chunk !== undefined) {
// Because Content-Length and Transfer-Encoding can't be present in the response headers together,
// Content-Length should be added only if there is no Transfer-Encoding header
var len;
if (chunk !== undefined && !this.get('Transfer-Encoding')) {
if (Buffer.isBuffer(chunk)) {
// get length of Buffer
len = chunk.length
+25
View File
@@ -592,4 +592,29 @@ describe('res', function(){
})
})
})
describe('when Transfer-Encoding header is present', function(){
var transferEncodings = [
'chunked',
'compress',
'deflate',
'gzip'
];
transferEncodings.forEach(function(encoding){
it('should not add Content-Length header if Transfer-Encoding header is equal to ' + encoding, function(done){
var app = express();
app.use(function(_, res){
res.status(200).set('Transfer-Encoding', encoding).send('');
});
request(app)
.get('/')
.expect(utils.shouldNotHaveHeader('Content-Length'))
.expect(utils.shouldHaveHeader('Transfer-Encoding'))
.expect(200, '', done);
})
});
})
})