strong-tie/inbound-calls
0
1'use strict'2 3const {4 kReplyIsError,5 kReplyHijacked6} = require('./symbols')7 8const diagnostics = require('node:diagnostics_channel')9const channels = diagnostics.tracingChannel('fastify.request.handler')10 11function wrapThenable (thenable, reply, store) {12 if (store) store.async = true13 thenable.then(function (payload) {14 if (reply[kReplyHijacked] === true) {15 return16 }17 18 if (store) {19 channels.asyncStart.publish(store)20 }21 22 try {23 // this is for async functions that are using reply.send directly24 //25 // since wrap-thenable will be called when using reply.send directly26 // without actual return. the response can be sent already or27 // the request may be terminated during the reply. in this situation,28 // it require an extra checking of request.aborted to see whether29 // the request is killed by client.30 if (payload !== undefined || (reply.sent === false && reply.raw.headersSent === false && reply.request.raw.aborted === false)) {31 // we use a try-catch internally to avoid adding a catch to another32 // promise, increase promise perf by 10%33 try {34 reply.send(payload)35 } catch (err) {36 reply[kReplyIsError] = true37 reply.send(err)38 }39 }40 } finally {41 if (store) {42 channels.asyncEnd.publish(store)43 }44 }45 }, function (err) {46 if (store) {47 store.error = err48 channels.error.publish(store) // note that error happens before asyncStart49 channels.asyncStart.publish(store)50 }51 52 try {53 if (reply.sent === true) {54 reply.log.error({ err }, 'Promise errored, but reply.sent = true was set')55 return56 }57 58 reply[kReplyIsError] = true59 60 reply.send(err)61 // The following should not happen62 /* c8 ignore next 3 */63 } catch (err) {64 // try-catch allow to re-throw error in error handler for async handler65 reply.send(err)66 } finally {67 if (store) {68 channels.asyncEnd.publish(store)69 }70 }71 })72}73 74module.exports = wrapThenable75 