Skip to content

Commit 18e5985

Browse files
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 <bjohansebas@gmail.com>
1 parent 59e205a commit 18e5985

3 files changed

Lines changed: 36 additions & 3 deletions

File tree

History.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
# Unreleased Changes
22

3+
## 🐞 Bug fixes
4+
5+
- 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)
6+
7+
8+
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
9+
310
## 🚀 Improvements
411

512
* 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)

lib/response.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,10 @@ res.send = function send(body) {
162162
var etagFn = app.get('etag fn')
163163
var generateETag = !this.get('ETag') && typeof etagFn === 'function'
164164

165-
// populate Content-Length
166-
var len
167-
if (chunk !== undefined) {
165+
// Because Content-Length and Transfer-Encoding can't be present in the response headers together,
166+
// Content-Length should be added only if there is no Transfer-Encoding header
167+
var len;
168+
if (chunk !== undefined && !this.get('Transfer-Encoding')) {
168169
if (Buffer.isBuffer(chunk)) {
169170
// get length of Buffer
170171
len = chunk.length

test/res.send.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,4 +592,29 @@ describe('res', function(){
592592
})
593593
})
594594
})
595+
596+
describe('when Transfer-Encoding header is present', function(){
597+
var transferEncodings = [
598+
'chunked',
599+
'compress',
600+
'deflate',
601+
'gzip'
602+
];
603+
604+
transferEncodings.forEach(function(encoding){
605+
it('should not add Content-Length header if Transfer-Encoding header is equal to ' + encoding, function(done){
606+
var app = express();
607+
608+
app.use(function(_, res){
609+
res.status(200).set('Transfer-Encoding', encoding).send('');
610+
});
611+
612+
request(app)
613+
.get('/')
614+
.expect(utils.shouldNotHaveHeader('Content-Length'))
615+
.expect(utils.shouldHaveHeader('Transfer-Encoding'))
616+
.expect(200, '', done);
617+
})
618+
});
619+
})
595620
})

0 commit comments

Comments
 (0)