UNPKG

fastify

Version:

Fast and low overhead web framework, for Node.js

195 lines (166 loc) 4.92 kB
'use strict' const t = require('tap') const test = t.test const proxyquire = require('proxyquire') const fs = require('node:fs') const Readable = require('node:stream').Readable const sget = require('simple-get').concat const Fastify = require('..') test('should destroy stream when response is ended', t => { t.plan(4) const stream = require('node:stream') const fastify = Fastify() fastify.get('/error', function (req, reply) { const reallyLongStream = new stream.Readable({ read: function () { }, destroy: function (err, callback) { t.ok('called') callback(err) } }) reply.code(200).send(reallyLongStream) reply.raw.end(Buffer.from('hello\n')) }) fastify.listen({ port: 0 }, err => { t.error(err) t.teardown(() => { fastify.close() }) sget(`http://localhost:${fastify.server.address().port}/error`, function (err, response) { t.error(err) t.equal(response.statusCode, 200) }) }) }) test('should mark reply as sent before pumping the payload stream into response for async route handler', t => { t.plan(3) const handleRequest = proxyquire('../lib/handleRequest', { './wrapThenable': (thenable, reply) => { thenable.then(function (payload) { t.equal(reply.sent, true) }) } }) const route = proxyquire('../lib/route', { './handleRequest': handleRequest }) const Fastify = proxyquire('..', { './lib/route': route }) const fastify = Fastify() fastify.get('/', async function (req, reply) { const stream = fs.createReadStream(__filename, 'utf8') return reply.code(200).send(stream) }) fastify.inject({ url: '/', method: 'GET' }, (err, res) => { t.error(err) t.equal(res.payload, fs.readFileSync(__filename, 'utf8')) fastify.close() }) }) test('reply.send handles aborted requests', t => { t.plan(2) const spyLogger = { level: 'error', fatal: () => { }, error: () => { t.fail('should not log an error') }, warn: () => { }, info: () => { }, debug: () => { }, trace: () => { }, child: () => { return spyLogger } } const fastify = Fastify({ logger: spyLogger }) fastify.get('/', (req, reply) => { setTimeout(() => { const stream = new Readable({ read: function () { this.push(null) } }) reply.send(stream) }, 6) }) fastify.listen({ port: 0 }, err => { t.error(err) t.teardown(() => { fastify.close() }) const port = fastify.server.address().port const http = require('node:http') const req = http.get(`http://localhost:${port}`) .on('error', (err) => { t.equal(err.code, 'ECONNRESET') fastify.close() }) setTimeout(() => { req.abort() }, 1) }) }) test('request terminated should not crash fastify', t => { t.plan(10) const spyLogger = { level: 'error', fatal: () => { }, error: () => { t.fail('should not log an error') }, warn: () => { }, info: () => { }, debug: () => { }, trace: () => { }, child: () => { return spyLogger } } const fastify = Fastify({ logger: spyLogger }) fastify.get('/', async (req, reply) => { const stream = new Readable() stream._read = () => { } reply.header('content-type', 'text/html; charset=utf-8') reply.header('transfer-encoding', 'chunked') stream.push('<h1>HTML</h1>') reply.send(stream) await new Promise((resolve) => { setTimeout(resolve, 100).unref() }) stream.push('<h1>should display on second stream</h1>') stream.push(null) return reply }) fastify.listen({ port: 0 }, err => { t.error(err) t.teardown(() => { fastify.close() }) const port = fastify.server.address().port const http = require('node:http') const req = http.get(`http://localhost:${port}`, function (res) { const { statusCode, headers } = res t.equal(statusCode, 200) t.equal(headers['content-type'], 'text/html; charset=utf-8') t.equal(headers['transfer-encoding'], 'chunked') res.on('data', function (chunk) { t.equal(chunk.toString(), '<h1>HTML</h1>') }) setTimeout(() => { req.destroy() // the server is not crash, we can connect it http.get(`http://localhost:${port}`, function (res) { const { statusCode, headers } = res t.equal(statusCode, 200) t.equal(headers['content-type'], 'text/html; charset=utf-8') t.equal(headers['transfer-encoding'], 'chunked') let payload = '' res.on('data', function (chunk) { payload += chunk.toString() }) res.on('end', function () { t.equal(payload, '<h1>HTML</h1><h1>should display on second stream</h1>') t.pass('should end properly') }) }) }, 1) }) }) })