fatsify核心功能示例测试!!!
This commit is contained in:
176
node_modules/fastify/lib/error-handler.js
generated
vendored
Normal file
176
node_modules/fastify/lib/error-handler.js
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
'use strict'
|
||||
|
||||
const statusCodes = require('node:http').STATUS_CODES
|
||||
const wrapThenable = require('./wrapThenable')
|
||||
const {
|
||||
kReplyHeaders,
|
||||
kReplyNextErrorHandler,
|
||||
kReplyIsRunningOnErrorHook,
|
||||
kReplyHasStatusCode,
|
||||
kRouteContext,
|
||||
kDisableRequestLogging
|
||||
} = require('./symbols.js')
|
||||
|
||||
const {
|
||||
FST_ERR_REP_INVALID_PAYLOAD_TYPE,
|
||||
FST_ERR_FAILED_ERROR_SERIALIZATION
|
||||
} = require('./errors')
|
||||
|
||||
const { getSchemaSerializer } = require('./schemas')
|
||||
|
||||
const serializeError = require('./error-serializer')
|
||||
|
||||
const rootErrorHandler = {
|
||||
func: defaultErrorHandler,
|
||||
toJSON () {
|
||||
return this.func.name.toString() + '()'
|
||||
}
|
||||
}
|
||||
|
||||
function handleError (reply, error, cb) {
|
||||
reply[kReplyIsRunningOnErrorHook] = false
|
||||
|
||||
const context = reply[kRouteContext]
|
||||
if (reply[kReplyNextErrorHandler] === false) {
|
||||
fallbackErrorHandler(error, reply, function (reply, payload) {
|
||||
try {
|
||||
reply.raw.writeHead(reply.raw.statusCode, reply[kReplyHeaders])
|
||||
} catch (error) {
|
||||
if (!reply.log[kDisableRequestLogging]) {
|
||||
reply.log.warn(
|
||||
{ req: reply.request, res: reply, err: error },
|
||||
error?.message
|
||||
)
|
||||
}
|
||||
reply.raw.writeHead(reply.raw.statusCode)
|
||||
}
|
||||
reply.raw.end(payload)
|
||||
})
|
||||
return
|
||||
}
|
||||
const errorHandler = reply[kReplyNextErrorHandler] || context.errorHandler
|
||||
|
||||
// In case the error handler throws, we set the next errorHandler so we can error again
|
||||
reply[kReplyNextErrorHandler] = Object.getPrototypeOf(errorHandler)
|
||||
|
||||
// we need to remove content-type to allow content-type guessing for serialization
|
||||
delete reply[kReplyHeaders]['content-type']
|
||||
delete reply[kReplyHeaders]['content-length']
|
||||
|
||||
const func = errorHandler.func
|
||||
|
||||
if (!func) {
|
||||
reply[kReplyNextErrorHandler] = false
|
||||
fallbackErrorHandler(error, reply, cb)
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const result = func(error, reply.request, reply)
|
||||
if (result !== undefined) {
|
||||
if (result !== null && typeof result.then === 'function') {
|
||||
wrapThenable(result, reply)
|
||||
} else {
|
||||
reply.send(result)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
reply.send(err)
|
||||
}
|
||||
}
|
||||
|
||||
function defaultErrorHandler (error, request, reply) {
|
||||
setErrorHeaders(error, reply)
|
||||
if (!reply[kReplyHasStatusCode] || reply.statusCode === 200) {
|
||||
const statusCode = error.statusCode || error.status
|
||||
reply.code(statusCode >= 400 ? statusCode : 500)
|
||||
}
|
||||
if (reply.statusCode < 500) {
|
||||
if (!reply.log[kDisableRequestLogging]) {
|
||||
reply.log.info(
|
||||
{ res: reply, err: error },
|
||||
error?.message
|
||||
)
|
||||
}
|
||||
} else {
|
||||
if (!reply.log[kDisableRequestLogging]) {
|
||||
reply.log.error(
|
||||
{ req: request, res: reply, err: error },
|
||||
error?.message
|
||||
)
|
||||
}
|
||||
}
|
||||
reply.send(error)
|
||||
}
|
||||
|
||||
function fallbackErrorHandler (error, reply, cb) {
|
||||
const res = reply.raw
|
||||
const statusCode = reply.statusCode
|
||||
reply[kReplyHeaders]['content-type'] = reply[kReplyHeaders]['content-type'] ?? 'application/json; charset=utf-8'
|
||||
let payload
|
||||
try {
|
||||
const serializerFn = getSchemaSerializer(reply[kRouteContext], statusCode, reply[kReplyHeaders]['content-type'])
|
||||
if (serializerFn === false) {
|
||||
payload = serializeError({
|
||||
error: statusCodes[statusCode + ''],
|
||||
code: error.code,
|
||||
message: error.message,
|
||||
statusCode
|
||||
})
|
||||
} else {
|
||||
payload = serializerFn(Object.create(error, {
|
||||
error: { value: statusCodes[statusCode + ''] },
|
||||
message: { value: error.message },
|
||||
statusCode: { value: statusCode }
|
||||
}))
|
||||
}
|
||||
} catch (err) {
|
||||
if (!reply.log[kDisableRequestLogging]) {
|
||||
// error is always FST_ERR_SCH_SERIALIZATION_BUILD because this is called from route/compileSchemasForSerialization
|
||||
reply.log.error({ err, statusCode: res.statusCode }, 'The serializer for the given status code failed')
|
||||
}
|
||||
reply.code(500)
|
||||
payload = serializeError(new FST_ERR_FAILED_ERROR_SERIALIZATION(err.message, error.message))
|
||||
}
|
||||
|
||||
if (typeof payload !== 'string' && !Buffer.isBuffer(payload)) {
|
||||
payload = serializeError(new FST_ERR_REP_INVALID_PAYLOAD_TYPE(typeof payload))
|
||||
}
|
||||
|
||||
reply[kReplyHeaders]['content-length'] = '' + Buffer.byteLength(payload)
|
||||
|
||||
cb(reply, payload)
|
||||
}
|
||||
|
||||
function buildErrorHandler (parent = rootErrorHandler, func) {
|
||||
if (!func) {
|
||||
return parent
|
||||
}
|
||||
|
||||
const errorHandler = Object.create(parent)
|
||||
errorHandler.func = func
|
||||
return errorHandler
|
||||
}
|
||||
|
||||
function setErrorHeaders (error, reply) {
|
||||
const res = reply.raw
|
||||
let statusCode = res.statusCode
|
||||
statusCode = (statusCode >= 400) ? statusCode : 500
|
||||
// treat undefined and null as same
|
||||
if (error != null) {
|
||||
if (error.headers !== undefined) {
|
||||
reply.headers(error.headers)
|
||||
}
|
||||
if (error.status >= 400) {
|
||||
statusCode = error.status
|
||||
} else if (error.statusCode >= 400) {
|
||||
statusCode = error.statusCode
|
||||
}
|
||||
}
|
||||
res.statusCode = statusCode
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildErrorHandler,
|
||||
handleError
|
||||
}
|
||||
Reference in New Issue
Block a user