strong-tie/inbound-calls
0
1'use strict'2 3const stream = require('node:stream')4const { test } = require('node:test')5const Fastify = require('..')6 7test('Creates a HEAD route for a GET one with prefixTrailingSlash', async (t) => {8 t.plan(1)9 10 const fastify = Fastify()11 12 const arr = []13 fastify.register((instance, opts, next) => {14 instance.addHook('onRoute', (routeOptions) => {15 arr.push(`${routeOptions.method} ${routeOptions.url}`)16 })17 18 instance.route({19 method: 'GET',20 path: '/',21 exposeHeadRoute: true,22 prefixTrailingSlash: 'both',23 handler: (req, reply) => {24 reply.send({ here: 'is coffee' })25 }26 })27 28 next()29 }, { prefix: '/v1' })30 31 await fastify.ready()32 33 t.assert.ok(true)34})35 36test('Will not create a HEAD route that is not GET', async t => {37 t.plan(8)38 39 const fastify = Fastify({ exposeHeadRoutes: true })40 41 fastify.route({42 method: 'GET',43 path: '/more-coffee',44 handler: (req, reply) => {45 reply.send({ here: 'is coffee' })46 }47 })48 49 fastify.route({50 method: 'GET',51 path: '/some-light',52 handler: (req, reply) => {53 reply.send()54 }55 })56 57 fastify.route({58 method: 'POST',59 path: '/something',60 handler: (req, reply) => {61 reply.send({ look: 'It is something!' })62 }63 })64 65 let res = await fastify.inject({66 method: 'HEAD',67 url: '/more-coffee'68 })69 70 t.assert.strictEqual(res.statusCode, 200)71 t.assert.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')72 t.assert.deepStrictEqual(res.body, '')73 74 res = await fastify.inject({75 method: 'HEAD',76 url: '/some-light'77 })78 79 t.assert.strictEqual(res.statusCode, 200)80 t.assert.strictEqual(res.headers['content-type'], undefined)81 t.assert.strictEqual(res.headers['content-length'], '0')82 t.assert.strictEqual(res.body, '')83 84 res = await fastify.inject({85 method: 'HEAD',86 url: '/something'87 })88 89 t.assert.strictEqual(res.statusCode, 404)90})91 92test('HEAD route should handle properly each response type', async t => {93 t.plan(20)94 95 const fastify = Fastify({ exposeHeadRoutes: true })96 const resString = 'Found me!'97 const resJSON = { here: 'is Johnny' }98 const resBuffer = Buffer.from('I am a buffer!')99 const resStream = stream.Readable.from('I am a stream!')100 101 fastify.route({102 method: 'GET',103 path: '/json',104 handler: (req, reply) => {105 reply.send(resJSON)106 }107 })108 109 fastify.route({110 method: 'GET',111 path: '/string',112 handler: (req, reply) => {113 reply.send(resString)114 }115 })116 117 fastify.route({118 method: 'GET',119 path: '/buffer',120 handler: (req, reply) => {121 reply.send(resBuffer)122 }123 })124 125 fastify.route({126 method: 'GET',127 path: '/buffer-with-content-type',128 handler: (req, reply) => {129 reply.headers({ 'content-type': 'image/jpeg' })130 reply.send(resBuffer)131 }132 })133 134 fastify.route({135 method: 'GET',136 path: '/stream',137 handler: (req, reply) => {138 return resStream139 }140 })141 142 let res = await fastify.inject({143 method: 'HEAD',144 url: '/json'145 })146 t.assert.strictEqual(res.statusCode, 200)147 t.assert.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8')148 t.assert.strictEqual(res.headers['content-length'], `${Buffer.byteLength(JSON.stringify(resJSON))}`)149 t.assert.deepStrictEqual(res.body, '')150 151 res = await fastify.inject({152 method: 'HEAD',153 url: '/string'154 })155 t.assert.strictEqual(res.statusCode, 200)156 t.assert.strictEqual(res.headers['content-type'], 'text/plain; charset=utf-8')157 t.assert.strictEqual(res.headers['content-length'], `${Buffer.byteLength(resString)}`)158 t.assert.strictEqual(res.body, '')159 160 res = await fastify.inject({161 method: 'HEAD',162 url: '/buffer'163 })164 t.assert.strictEqual(res.statusCode, 200)165 t.assert.strictEqual(res.headers['content-type'], 'application/octet-stream')166 t.assert.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)167 t.assert.strictEqual(res.body, '')168 169 res = await fastify.inject({170 method: 'HEAD',171 url: '/buffer-with-content-type'172 })173 t.assert.strictEqual(res.statusCode, 200)174 t.assert.strictEqual(res.headers['content-type'], 'image/jpeg')175 t.assert.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)176 t.assert.strictEqual(res.body, '')177 178 res = await fastify.inject({179 method: 'HEAD',180 url: '/stream'181 })182 t.assert.strictEqual(res.statusCode, 200)183 t.assert.strictEqual(res.headers['content-type'], undefined)184 t.assert.strictEqual(res.headers['content-length'], undefined)185 t.assert.strictEqual(res.body, '')186})187 188test('HEAD route should respect custom onSend handlers', async t => {189 t.plan(5)190 191 let counter = 0192 const resBuffer = Buffer.from('I am a coffee!')193 const fastify = Fastify({ exposeHeadRoutes: true })194 const customOnSend = (res, reply, payload, done) => {195 counter = counter + 1196 done(null, payload)197 }198 199 fastify.route({200 method: 'GET',201 path: '/more-coffee',202 handler: (req, reply) => {203 reply.send(resBuffer)204 },205 onSend: [customOnSend, customOnSend]206 })207 208 const res = await fastify.inject({209 method: 'HEAD',210 url: '/more-coffee'211 })212 213 t.assert.strictEqual(res.statusCode, 200)214 t.assert.strictEqual(res.headers['content-type'], 'application/octet-stream')215 t.assert.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)216 t.assert.strictEqual(res.body, '')217 t.assert.strictEqual(counter, 2)218})219 220test('route onSend can be function or array of functions', async t => {221 t.plan(10)222 const counters = { single: 0, multiple: 0 }223 224 const resBuffer = Buffer.from('I am a coffee!')225 const fastify = Fastify({ exposeHeadRoutes: true })226 227 fastify.route({228 method: 'GET',229 path: '/coffee',230 handler: () => resBuffer,231 onSend: (res, reply, payload, done) => {232 counters.single += 1233 done(null, payload)234 }235 })236 237 const customOnSend = (res, reply, payload, done) => {238 counters.multiple += 1239 done(null, payload)240 }241 242 fastify.route({243 method: 'GET',244 path: '/more-coffee',245 handler: () => resBuffer,246 onSend: [customOnSend, customOnSend]247 })248 249 let res = await fastify.inject({ method: 'HEAD', url: '/coffee' })250 t.assert.strictEqual(res.statusCode, 200)251 t.assert.strictEqual(res.headers['content-type'], 'application/octet-stream')252 t.assert.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)253 t.assert.strictEqual(res.body, '')254 t.assert.strictEqual(counters.single, 1)255 256 res = await fastify.inject({ method: 'HEAD', url: '/more-coffee' })257 t.assert.strictEqual(res.statusCode, 200)258 t.assert.strictEqual(res.headers['content-type'], 'application/octet-stream')259 t.assert.strictEqual(res.headers['content-length'], `${resBuffer.byteLength}`)260 t.assert.strictEqual(res.body, '')261 t.assert.strictEqual(counters.multiple, 2)262})263 264test('no warning for exposeHeadRoute', async t => {265 const fastify = Fastify()266 267 fastify.route({268 method: 'GET',269 path: '/more-coffee',270 exposeHeadRoute: true,271 async handler () {272 return 'hello world'273 }274 })275 276 const listener = (w) => {277 t.assert.fail('no warning')278 }279 280 process.on('warning', listener)281 282 await fastify.listen({ port: 0 })283 284 process.removeListener('warning', listener)285 286 await fastify.close()287})288 