'use strict' var assert = require('node:assert') const { Buffer } = require('node:buffer'); var express = require('..'); var methods = require('../lib/utils').methods; var request = require('supertest'); var utils = require('./support/utils'); var shouldSkipQuery = require('./support/utils').shouldSkipQuery describe('res', function(){ describe('.send()', function(){ it('should set body to ""', function(done){ var app = express(); app.use(function(req, res){ res.send(); }); request(app) .get('/') .expect(200, '', done); }) }) describe('.send(null)', function(){ it('should set body to ""', function(done){ var app = express(); app.use(function(req, res){ res.send(null); }); request(app) .get('/') .expect('Content-Length', '0') .expect(200, '', done); }) }) describe('.send(undefined)', function(){ it('should set body to ""', function(done){ var app = express(); app.use(function(req, res){ res.send(undefined); }); request(app) .get('/') .expect(200, '', done); }) }) describe('.send(Number)', function(){ it('should send as application/json', function(done){ var app = express(); app.use(function(req, res){ res.send(1000); }); request(app) .get('/') .expect('Content-Type', 'application/json; charset=utf-8') .expect(200, '1000', done) }) }) describe('.send(String)', function(){ it('should send as html', function(done){ var app = express(); app.use(function(req, res){ res.send('
hey
'); }); request(app) .get('/') .expect('Content-Type', 'text/html; charset=utf-8') .expect(200, 'hey
', done); }) it('should set ETag', function (done) { var app = express(); app.use(function (req, res) { var str = Array(1000).join('-'); res.send(str); }); request(app) .get('/') .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') .expect(200, done); }) it('should not override Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/plain').send('hey'); }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200, 'hey', done); }) it('should override charset in Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/plain; charset=iso-8859-1').send('hey'); }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200, 'hey', done); }) it('should keep charset in Content-Type for Buffers', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/plain; charset=iso-8859-1').send(Buffer.from('hi')) }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=iso-8859-1') .expect(200, 'hi', done); }) }) describe('.send(Buffer)', function(){ it('should send as octet-stream', function(done){ var app = express(); app.use(function(req, res){ res.send(Buffer.from('hello')) }); request(app) .get('/') .expect(200) .expect('Content-Type', 'application/octet-stream') .expect(utils.shouldHaveBody(Buffer.from('hello'))) .end(done) }) it('should set ETag', function (done) { var app = express(); app.use(function (req, res) { res.send(Buffer.alloc(999, '-')) }); request(app) .get('/') .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') .expect(200, done); }) it('should not override Content-Type', function(done){ var app = express(); app.use(function(req, res){ res.set('Content-Type', 'text/plain').send(Buffer.from('hey')) }); request(app) .get('/') .expect('Content-Type', 'text/plain; charset=utf-8') .expect(200, 'hey', done); }) it('should accept Uint8Array', function(done){ var app = express(); app.use(function(req, res){ const encodedHey = new TextEncoder().encode("hey"); res.set("Content-Type", "text/plain").send(encodedHey); }) request(app) .get("/") .expect("Content-Type", "text/plain; charset=utf-8") .expect(200, "hey", done); }) it('should not override ETag', function (done) { var app = express() app.use(function (req, res) { res.type('text/plain').set('ETag', '"foo"').send(Buffer.from('hey')) }) request(app) .get('/') .expect('ETag', '"foo"') .expect(200, 'hey', done) }) }) describe('.send(Object)', function(){ it('should send as application/json', function(done){ var app = express(); app.use(function(req, res){ res.send({ name: 'tobi' }); }); request(app) .get('/') .expect('Content-Type', 'application/json; charset=utf-8') .expect(200, '{"name":"tobi"}', done) }) }) describe('when the request method is HEAD', function(){ it('should ignore the body', function(done){ var app = express(); app.use(function(req, res){ res.send('yay'); }); request(app) .head('/') .expect(200) .expect(utils.shouldNotHaveBody()) .end(done) }) }) describe('when .statusCode is 204', function(){ it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){ var app = express(); app.use(function(req, res){ res.status(204).set('Transfer-Encoding', 'chunked').send('foo'); }); request(app) .get('/') .expect(utils.shouldNotHaveHeader('Content-Type')) .expect(utils.shouldNotHaveHeader('Content-Length')) .expect(utils.shouldNotHaveHeader('Transfer-Encoding')) .expect(204, '', done); }) }) describe('when .statusCode is 205', function () { it('should strip Transfer-Encoding field and body, set Content-Length', function (done) { var app = express() app.use(function (req, res) { res.status(205).set('Transfer-Encoding', 'chunked').send('foo') }) request(app) .get('/') .expect(utils.shouldNotHaveHeader('Transfer-Encoding')) .expect('Content-Length', '0') .expect(205, '', done) }) }) describe('when .statusCode is 304', function(){ it('should strip Content-* fields, Transfer-Encoding field, and body', function(done){ var app = express(); app.use(function(req, res){ res.status(304).set('Transfer-Encoding', 'chunked').send('foo'); }); request(app) .get('/') .expect(utils.shouldNotHaveHeader('Content-Type')) .expect(utils.shouldNotHaveHeader('Content-Length')) .expect(utils.shouldNotHaveHeader('Transfer-Encoding')) .expect(304, '', done); }) }) it('should always check regardless of length', function(done){ var app = express(); var etag = '"asdf"'; app.use(function(req, res, next){ res.set('ETag', etag); res.send('hey'); }); request(app) .get('/') .set('If-None-Match', etag) .expect(304, done); }) it('should respond with 304 Not Modified when fresh', function(done){ var app = express(); var etag = '"asdf"'; app.use(function(req, res){ var str = Array(1000).join('-'); res.set('ETag', etag); res.send(str); }); request(app) .get('/') .set('If-None-Match', etag) .expect(304, done); }) it('should not perform freshness check unless 2xx or 304', function(done){ var app = express(); var etag = '"asdf"'; app.use(function(req, res, next){ res.status(500); res.set('ETag', etag); res.send('hey'); }); request(app) .get('/') .set('If-None-Match', etag) .expect('hey') .expect(500, done); }) it('should not support jsonp callbacks', function(done){ var app = express(); app.use(function(req, res){ res.send({ foo: 'bar' }); }); request(app) .get('/?callback=foo') .expect('{"foo":"bar"}', done); }) it('should be chainable', function (done) { var app = express() app.use(function (req, res) { assert.equal(res.send('hey'), res) }) request(app) .get('/') .expect(200, 'hey', done) }) describe('"etag" setting', function () { describe('when enabled', function () { it('should send ETag', function (done) { var app = express(); app.use(function (req, res) { res.send('kajdslfkasdf'); }); app.enable('etag'); request(app) .get('/') .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"') .expect(200, done); }); methods.forEach(function (method) { if (method === 'connect') return; it('should send ETag in response to ' + method.toUpperCase() + ' request', function (done) { if (method === 'query' && shouldSkipQuery(process.versions.node)) { this.skip() } var app = express(); app[method]('/', function (req, res) { res.send('kajdslfkasdf'); }); request(app) [method]('/') .expect('ETag', 'W/"c-IgR/L5SF7CJQff4wxKGF/vfPuZ0"') .expect(200, done); }) }); it('should send ETag for empty string response', function (done) { var app = express(); app.use(function (req, res) { res.send(''); }); app.enable('etag'); request(app) .get('/') .expect('ETag', 'W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"') .expect(200, done); }) it('should send ETag for long response', function (done) { var app = express(); app.use(function (req, res) { var str = Array(1000).join('-'); res.send(str); }); app.enable('etag'); request(app) .get('/') .expect('ETag', 'W/"3e7-qPnkJ3CVdVhFJQvUBfF10TmVA7g"') .expect(200, done); }); it('should not override ETag when manually set', function (done) { var app = express(); app.use(function (req, res) { res.set('etag', '"asdf"'); res.send('hello!'); }); app.enable('etag'); request(app) .get('/') .expect('ETag', '"asdf"') .expect(200, done); }); it('should not send ETag for res.send()', function (done) { var app = express(); app.use(function (req, res) { res.send(); }); app.enable('etag'); request(app) .get('/') .expect(utils.shouldNotHaveHeader('ETag')) .expect(200, done); }) }); describe('when disabled', function () { it('should send no ETag', function (done) { var app = express(); app.use(function (req, res) { var str = Array(1000).join('-'); res.send(str); }); app.disable('etag'); request(app) .get('/') .expect(utils.shouldNotHaveHeader('ETag')) .expect(200, done); }); it('should send ETag when manually set', function (done) { var app = express(); app.disable('etag'); app.use(function (req, res) { res.set('etag', '"asdf"'); res.send('hello!'); }); request(app) .get('/') .expect('ETag', '"asdf"') .expect(200, done); }); }); describe('when "strong"', function () { it('should send strong ETag', function (done) { var app = express(); app.set('etag', 'strong'); app.use(function (req, res) { res.send('hello, world!'); }); request(app) .get('/') .expect('ETag', '"d-HwnTDHB9U/PRbFMN1z1wps51lqk"') .expect(200, done); }) }) describe('when "weak"', function () { it('should send weak ETag', function (done) { var app = express(); app.set('etag', 'weak'); app.use(function (req, res) { res.send('hello, world!'); }); request(app) .get('/') .expect('ETag', 'W/"d-HwnTDHB9U/PRbFMN1z1wps51lqk"') .expect(200, done) }) }) describe('when a function', function () { it('should send custom ETag', function (done) { var app = express(); app.set('etag', function (body, encoding) { var chunk = !Buffer.isBuffer(body) ? Buffer.from(body, encoding) : body; assert.strictEqual(chunk.toString(), 'hello, world!') return '"custom"'; }); app.use(function (req, res) { res.send('hello, world!'); }); request(app) .get('/') .expect('ETag', '"custom"') .expect(200, done); }) it('should not send falsy ETag', function (done) { var app = express(); app.set('etag', function (body, encoding) { return undefined; }); app.use(function (req, res) { res.send('hello, world!'); }); request(app) .get('/') .expect(utils.shouldNotHaveHeader('ETag')) .expect(200, done); }) }) }) })