UNPKG

fastify

Version:

Fast and low overhead web framework, for Node.js

340 lines (298 loc) 8.64 kB
'use strict' const { test } = require('node:test') const { connect } = require('node:net') const Fastify = require('..') // RFC9112 // https://www.rfc-editor.org/rfc/rfc9112 test('Return 400 when Host header is missing', (t, done) => { t.plan(2) let data = Buffer.alloc(0) const fastify = Fastify() t.after(() => fastify.close()) fastify.get('/', async function () { t.assert.fail('should not reach handler') return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 400 Bad Request/ ) done() }) }) }) test('Return 400 when Host header is missing with trust proxy', (t, done) => { t.plan(2) let data = Buffer.alloc(0) const fastify = Fastify({ trustProxy: true }) t.after(() => fastify.close()) fastify.get('/', async function () { t.assert.fail('should not reach handler') return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 400 Bad Request/ ) done() }) }) }) test('Return 200 when Host header is empty', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\nHost:\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) test('Return 200 when Host header is empty with trust proxy', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ trustProxy: true, keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\nHost:\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) // Node.js allows exploiting RFC9112 // https://nodejs.org/docs/latest-v22.x/api/http.html#httpcreateserveroptions-requestlistener test('Return 200 when Host header is missing and http.requireHostHeader = false', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ http: { requireHostHeader: false }, keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) test('Return 200 when Host header is missing and http.requireHostHeader = false with trust proxy', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ http: { requireHostHeader: false }, trustProxy: true, keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) test('Return 200 when Host header is missing using HTTP/1.0', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.0\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) test('Return 200 when Host header is missing with trust proxy using HTTP/1.0', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ trustProxy: true, keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.0\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) test('Return 200 when Host header is removed by schema', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', { schema: { headers: { type: 'object', properties: {}, additionalProperties: false } } }, async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) }) test('Return 200 when Host header is removed by schema with trust proxy', (t, done) => { t.plan(5) let data = Buffer.alloc(0) const fastify = Fastify({ trustProxy: true, keepAliveTimeout: 10 }) t.after(() => fastify.close()) fastify.get('/', { schema: { headers: { type: 'object', properties: {}, additionalProperties: false } } }, async function (request) { t.assert.strictEqual(request.host, '') t.assert.strictEqual(request.hostname, '') t.assert.strictEqual(request.port, null) return { ok: true } }) fastify.listen({ port: 0 }, err => { t.assert.ifError(err) const socket = connect(fastify.server.address().port) socket.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n') socket.on('data', c => (data = Buffer.concat([data, c]))) socket.on('end', () => { t.assert.match( data.toString('utf-8'), /^HTTP\/1.1 200 OK/ ) done() }) }) })