strong-tie/inbound-calls
0
1'use strict'2 3const { test } = require('node:test')4const { connect } = require('node:net')5const Fastify = require('..')6 7// RFC91128// https://www.rfc-editor.org/rfc/rfc91129test('Return 400 when Host header is missing', (t, done) => {10 t.plan(2)11 let data = Buffer.alloc(0)12 const fastify = Fastify()13 14 t.after(() => fastify.close())15 16 fastify.get('/', async function () {17 t.assert.fail('should not reach handler')18 return { ok: true }19 })20 fastify.listen({ port: 0 }, err => {21 t.assert.ifError(err)22 23 const socket = connect(fastify.server.address().port)24 socket.write('GET / HTTP/1.1\r\n\r\n')25 socket.on('data', c => (data = Buffer.concat([data, c])))26 socket.on('end', () => {27 t.assert.match(28 data.toString('utf-8'),29 /^HTTP\/1.1 400 Bad Request/30 )31 done()32 })33 })34})35 36test('Return 400 when Host header is missing with trust proxy', (t, done) => {37 t.plan(2)38 let data = Buffer.alloc(0)39 const fastify = Fastify({40 trustProxy: true41 })42 43 t.after(() => fastify.close())44 45 fastify.get('/', async function () {46 t.assert.fail('should not reach handler')47 return { ok: true }48 })49 fastify.listen({ port: 0 }, err => {50 t.assert.ifError(err)51 52 const socket = connect(fastify.server.address().port)53 socket.write('GET / HTTP/1.1\r\n\r\n')54 socket.on('data', c => (data = Buffer.concat([data, c])))55 socket.on('end', () => {56 t.assert.match(57 data.toString('utf-8'),58 /^HTTP\/1.1 400 Bad Request/59 )60 done()61 })62 })63})64 65test('Return 200 when Host header is empty', (t, done) => {66 t.plan(5)67 let data = Buffer.alloc(0)68 const fastify = Fastify({69 keepAliveTimeout: 1070 })71 72 t.after(() => fastify.close())73 74 fastify.get('/', async function (request) {75 t.assert.strictEqual(request.host, '')76 t.assert.strictEqual(request.hostname, '')77 t.assert.strictEqual(request.port, null)78 return { ok: true }79 })80 fastify.listen({ port: 0 }, err => {81 t.assert.ifError(err)82 83 const socket = connect(fastify.server.address().port)84 socket.write('GET / HTTP/1.1\r\nHost:\r\n\r\n')85 socket.on('data', c => (data = Buffer.concat([data, c])))86 socket.on('end', () => {87 t.assert.match(88 data.toString('utf-8'),89 /^HTTP\/1.1 200 OK/90 )91 done()92 })93 })94})95 96test('Return 200 when Host header is empty with trust proxy', (t, done) => {97 t.plan(5)98 let data = Buffer.alloc(0)99 const fastify = Fastify({100 trustProxy: true,101 keepAliveTimeout: 10102 })103 104 t.after(() => fastify.close())105 106 fastify.get('/', async function (request) {107 t.assert.strictEqual(request.host, '')108 t.assert.strictEqual(request.hostname, '')109 t.assert.strictEqual(request.port, null)110 return { ok: true }111 })112 fastify.listen({ port: 0 }, err => {113 t.assert.ifError(err)114 115 const socket = connect(fastify.server.address().port)116 socket.write('GET / HTTP/1.1\r\nHost:\r\n\r\n')117 socket.on('data', c => (data = Buffer.concat([data, c])))118 socket.on('end', () => {119 t.assert.match(120 data.toString('utf-8'),121 /^HTTP\/1.1 200 OK/122 )123 done()124 })125 })126})127 128// Node.js allows exploiting RFC9112129// https://nodejs.org/docs/latest-v22.x/api/http.html#httpcreateserveroptions-requestlistener130test('Return 200 when Host header is missing and http.requireHostHeader = false', (t, done) => {131 t.plan(5)132 let data = Buffer.alloc(0)133 const fastify = Fastify({134 http: {135 requireHostHeader: false136 },137 keepAliveTimeout: 10138 })139 140 t.after(() => fastify.close())141 142 fastify.get('/', async function (request) {143 t.assert.strictEqual(request.host, '')144 t.assert.strictEqual(request.hostname, '')145 t.assert.strictEqual(request.port, null)146 return { ok: true }147 })148 fastify.listen({ port: 0 }, err => {149 t.assert.ifError(err)150 151 const socket = connect(fastify.server.address().port)152 socket.write('GET / HTTP/1.1\r\n\r\n')153 socket.on('data', c => (data = Buffer.concat([data, c])))154 socket.on('end', () => {155 t.assert.match(156 data.toString('utf-8'),157 /^HTTP\/1.1 200 OK/158 )159 done()160 })161 })162})163 164test('Return 200 when Host header is missing and http.requireHostHeader = false with trust proxy', (t, done) => {165 t.plan(5)166 let data = Buffer.alloc(0)167 const fastify = Fastify({168 http: {169 requireHostHeader: false170 },171 trustProxy: true,172 keepAliveTimeout: 10173 })174 175 t.after(() => fastify.close())176 177 fastify.get('/', async function (request) {178 t.assert.strictEqual(request.host, '')179 t.assert.strictEqual(request.hostname, '')180 t.assert.strictEqual(request.port, null)181 return { ok: true }182 })183 fastify.listen({ port: 0 }, err => {184 t.assert.ifError(err)185 186 const socket = connect(fastify.server.address().port)187 socket.write('GET / HTTP/1.1\r\n\r\n')188 socket.on('data', c => (data = Buffer.concat([data, c])))189 socket.on('end', () => {190 t.assert.match(191 data.toString('utf-8'),192 /^HTTP\/1.1 200 OK/193 )194 done()195 })196 })197})198 199test('Return 200 when Host header is missing using HTTP/1.0', (t, done) => {200 t.plan(5)201 let data = Buffer.alloc(0)202 const fastify = Fastify({203 keepAliveTimeout: 10204 })205 206 t.after(() => fastify.close())207 208 fastify.get('/', async function (request) {209 t.assert.strictEqual(request.host, '')210 t.assert.strictEqual(request.hostname, '')211 t.assert.strictEqual(request.port, null)212 return { ok: true }213 })214 fastify.listen({ port: 0 }, err => {215 t.assert.ifError(err)216 217 const socket = connect(fastify.server.address().port)218 socket.write('GET / HTTP/1.0\r\n\r\n')219 socket.on('data', c => (data = Buffer.concat([data, c])))220 socket.on('end', () => {221 t.assert.match(222 data.toString('utf-8'),223 /^HTTP\/1.1 200 OK/224 )225 done()226 })227 })228})229 230test('Return 200 when Host header is missing with trust proxy using HTTP/1.0', (t, done) => {231 t.plan(5)232 let data = Buffer.alloc(0)233 const fastify = Fastify({234 trustProxy: true,235 keepAliveTimeout: 10236 })237 238 t.after(() => fastify.close())239 240 fastify.get('/', async function (request) {241 t.assert.strictEqual(request.host, '')242 t.assert.strictEqual(request.hostname, '')243 t.assert.strictEqual(request.port, null)244 return { ok: true }245 })246 fastify.listen({ port: 0 }, err => {247 t.assert.ifError(err)248 249 const socket = connect(fastify.server.address().port)250 socket.write('GET / HTTP/1.0\r\n\r\n')251 socket.on('data', c => (data = Buffer.concat([data, c])))252 socket.on('end', () => {253 t.assert.match(254 data.toString('utf-8'),255 /^HTTP\/1.1 200 OK/256 )257 done()258 })259 })260})261 262test('Return 200 when Host header is removed by schema', (t, done) => {263 t.plan(5)264 let data = Buffer.alloc(0)265 const fastify = Fastify({266 keepAliveTimeout: 10267 })268 269 t.after(() => fastify.close())270 271 fastify.get('/', {272 schema: {273 headers: {274 type: 'object',275 properties: {},276 additionalProperties: false277 }278 }279 }, async function (request) {280 t.assert.strictEqual(request.host, '')281 t.assert.strictEqual(request.hostname, '')282 t.assert.strictEqual(request.port, null)283 return { ok: true }284 })285 fastify.listen({ port: 0 }, err => {286 t.assert.ifError(err)287 288 const socket = connect(fastify.server.address().port)289 socket.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')290 socket.on('data', c => (data = Buffer.concat([data, c])))291 socket.on('end', () => {292 t.assert.match(293 data.toString('utf-8'),294 /^HTTP\/1.1 200 OK/295 )296 done()297 })298 })299})300 301test('Return 200 when Host header is removed by schema with trust proxy', (t, done) => {302 t.plan(5)303 let data = Buffer.alloc(0)304 const fastify = Fastify({305 trustProxy: true,306 keepAliveTimeout: 10307 })308 309 t.after(() => fastify.close())310 311 fastify.get('/', {312 schema: {313 headers: {314 type: 'object',315 properties: {},316 additionalProperties: false317 }318 }319 }, async function (request) {320 t.assert.strictEqual(request.host, '')321 t.assert.strictEqual(request.hostname, '')322 t.assert.strictEqual(request.port, null)323 return { ok: true }324 })325 fastify.listen({ port: 0 }, err => {326 t.assert.ifError(err)327 328 const socket = connect(fastify.server.address().port)329 socket.write('GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')330 socket.on('data', c => (data = Buffer.concat([data, c])))331 socket.on('end', () => {332 t.assert.match(333 data.toString('utf-8'),334 /^HTTP\/1.1 200 OK/335 )336 done()337 })338 })339})340 