Aktueller Stand
This commit is contained in:
211
backend/node_modules/fastify/lib/route.js
generated
vendored
211
backend/node_modules/fastify/lib/route.js
generated
vendored
@@ -2,16 +2,10 @@
|
||||
|
||||
const FindMyWay = require('find-my-way')
|
||||
const Context = require('./context')
|
||||
const handleRequest = require('./handleRequest')
|
||||
const handleRequest = require('./handle-request.js')
|
||||
const { onRequestAbortHookRunner, lifecycleHooks, preParsingHookRunner, onTimeoutHookRunner, onRequestHookRunner } = require('./hooks')
|
||||
const { supportedMethods } = require('./httpMethods')
|
||||
const { normalizeSchema } = require('./schemas')
|
||||
const { parseHeadOnSendHandlers } = require('./headRoute')
|
||||
const {
|
||||
FSTDEP007,
|
||||
FSTDEP008,
|
||||
FSTDEP014
|
||||
} = require('./warnings')
|
||||
const { parseHeadOnSendHandlers } = require('./head-route.js')
|
||||
|
||||
const {
|
||||
compileSchemasForValidation,
|
||||
@@ -21,7 +15,6 @@ const {
|
||||
const {
|
||||
FST_ERR_SCH_VALIDATION_BUILD,
|
||||
FST_ERR_SCH_SERIALIZATION_BUILD,
|
||||
FST_ERR_DEFAULT_ROUTE_INVALID_TYPE,
|
||||
FST_ERR_DUPLICATED_ROUTE,
|
||||
FST_ERR_INVALID_URL,
|
||||
FST_ERR_HOOK_INVALID_HANDLER,
|
||||
@@ -38,6 +31,7 @@ const {
|
||||
|
||||
const {
|
||||
kRoutePrefix,
|
||||
kSupportedHTTPMethods,
|
||||
kLogLevel,
|
||||
kLogSerializers,
|
||||
kHooks,
|
||||
@@ -55,11 +49,26 @@ const {
|
||||
kRouteContext
|
||||
} = require('./symbols.js')
|
||||
const { buildErrorHandler } = require('./error-handler')
|
||||
const { createChildLogger } = require('./logger')
|
||||
const { getGenReqId } = require('./reqIdGenFactory.js')
|
||||
const { createChildLogger } = require('./logger-factory.js')
|
||||
const { getGenReqId } = require('./req-id-gen-factory.js')
|
||||
const { FSTDEP022 } = require('./warnings')
|
||||
|
||||
const routerKeys = [
|
||||
'allowUnsafeRegex',
|
||||
'buildPrettyMeta',
|
||||
'caseSensitive',
|
||||
'constraints',
|
||||
'defaultRoute',
|
||||
'ignoreDuplicateSlashes',
|
||||
'ignoreTrailingSlash',
|
||||
'maxParamLength',
|
||||
'onBadUrl',
|
||||
'querystringParser',
|
||||
'useSemicolonDelimiter'
|
||||
]
|
||||
|
||||
function buildRouting (options) {
|
||||
const router = FindMyWay(options.config)
|
||||
const router = FindMyWay(options)
|
||||
|
||||
let avvio
|
||||
let fourOhFour
|
||||
@@ -68,11 +77,11 @@ function buildRouting (options) {
|
||||
let setupResponseListeners
|
||||
let throwIfAlreadyStarted
|
||||
let disableRequestLogging
|
||||
let disableRequestLoggingFn
|
||||
let ignoreTrailingSlash
|
||||
let ignoreDuplicateSlashes
|
||||
let return503OnClosing
|
||||
let globalExposeHeadRoutes
|
||||
let validateHTTPVersion
|
||||
let keepAliveConnections
|
||||
|
||||
let closing = false
|
||||
@@ -85,35 +94,26 @@ function buildRouting (options) {
|
||||
setup (options, fastifyArgs) {
|
||||
avvio = fastifyArgs.avvio
|
||||
fourOhFour = fastifyArgs.fourOhFour
|
||||
logger = fastifyArgs.logger
|
||||
logger = options.logger
|
||||
hasLogger = fastifyArgs.hasLogger
|
||||
setupResponseListeners = fastifyArgs.setupResponseListeners
|
||||
throwIfAlreadyStarted = fastifyArgs.throwIfAlreadyStarted
|
||||
validateHTTPVersion = fastifyArgs.validateHTTPVersion
|
||||
|
||||
globalExposeHeadRoutes = options.exposeHeadRoutes
|
||||
disableRequestLogging = options.disableRequestLogging
|
||||
ignoreTrailingSlash = options.ignoreTrailingSlash
|
||||
ignoreDuplicateSlashes = options.ignoreDuplicateSlashes
|
||||
return503OnClosing = Object.prototype.hasOwnProperty.call(options, 'return503OnClosing') ? options.return503OnClosing : true
|
||||
if (typeof disableRequestLogging === 'function') {
|
||||
disableRequestLoggingFn = options.disableRequestLogging
|
||||
}
|
||||
|
||||
ignoreTrailingSlash = options.routerOptions.ignoreTrailingSlash
|
||||
ignoreDuplicateSlashes = options.routerOptions.ignoreDuplicateSlashes
|
||||
return503OnClosing = Object.hasOwn(options, 'return503OnClosing') ? options.return503OnClosing : true
|
||||
keepAliveConnections = fastifyArgs.keepAliveConnections
|
||||
},
|
||||
routing: router.lookup.bind(router), // router func to find the right handler to call
|
||||
route, // configure a route in the fastify instance
|
||||
hasRoute,
|
||||
prepareRoute,
|
||||
getDefaultRoute: function () {
|
||||
FSTDEP014()
|
||||
return router.defaultRoute
|
||||
},
|
||||
setDefaultRoute: function (defaultRoute) {
|
||||
FSTDEP014()
|
||||
if (typeof defaultRoute !== 'function') {
|
||||
throw new FST_ERR_DEFAULT_ROUTE_INVALID_TYPE()
|
||||
}
|
||||
|
||||
router.defaultRoute = defaultRoute
|
||||
},
|
||||
routeHandler,
|
||||
closeRoutes: () => { closing = true },
|
||||
printRoutes: router.prettyPrint.bind(router),
|
||||
@@ -169,10 +169,11 @@ function buildRouting (options) {
|
||||
|
||||
function hasRoute ({ options }) {
|
||||
const normalizedMethod = options.method?.toUpperCase() ?? ''
|
||||
return findRoute({
|
||||
...options,
|
||||
method: normalizedMethod
|
||||
}) !== null
|
||||
return router.hasRoute(
|
||||
normalizedMethod,
|
||||
options.url || '',
|
||||
options.constraints
|
||||
)
|
||||
}
|
||||
|
||||
function findRoute (options) {
|
||||
@@ -200,36 +201,13 @@ function buildRouting (options) {
|
||||
* @param {{ options: import('../fastify').RouteOptions, isFastify: boolean }}
|
||||
*/
|
||||
function route ({ options, isFastify }) {
|
||||
throwIfAlreadyStarted('Cannot add route!')
|
||||
|
||||
// Since we are mutating/assigning only top level props, it is fine to have a shallow copy using the spread operator
|
||||
const opts = { ...options }
|
||||
|
||||
const { exposeHeadRoute } = opts
|
||||
const hasRouteExposeHeadRouteFlag = exposeHeadRoute != null
|
||||
const shouldExposeHead = hasRouteExposeHeadRouteFlag ? exposeHeadRoute : globalExposeHeadRoutes
|
||||
|
||||
const isGetRoute = opts.method === 'GET' ||
|
||||
(Array.isArray(opts.method) && opts.method.includes('GET'))
|
||||
const isHeadRoute = opts.method === 'HEAD' ||
|
||||
(Array.isArray(opts.method) && opts.method.includes('HEAD'))
|
||||
|
||||
// we need to clone a set of initial options for HEAD route
|
||||
const headOpts = shouldExposeHead && isGetRoute ? { ...options } : null
|
||||
|
||||
throwIfAlreadyStarted('Cannot add route!')
|
||||
|
||||
const path = opts.url || opts.path || ''
|
||||
|
||||
if (Array.isArray(opts.method)) {
|
||||
// eslint-disable-next-line no-var
|
||||
for (var i = 0; i < opts.method.length; ++i) {
|
||||
opts.method[i] = normalizeAndValidateMethod(opts.method[i])
|
||||
validateSchemaBodyOption(opts.method[i], path, opts.schema)
|
||||
}
|
||||
} else {
|
||||
opts.method = normalizeAndValidateMethod(opts.method)
|
||||
validateSchemaBodyOption(opts.method, path, opts.schema)
|
||||
}
|
||||
|
||||
if (!opts.handler) {
|
||||
throw new FST_ERR_ROUTE_MISSING_HANDLER(opts.method, path)
|
||||
}
|
||||
@@ -240,6 +218,30 @@ function buildRouting (options) {
|
||||
|
||||
validateBodyLimitOption(opts.bodyLimit)
|
||||
|
||||
const shouldExposeHead = opts.exposeHeadRoute ?? globalExposeHeadRoutes
|
||||
|
||||
let isGetRoute = false
|
||||
let isHeadRoute = false
|
||||
|
||||
if (Array.isArray(opts.method)) {
|
||||
for (let i = 0; i < opts.method.length; ++i) {
|
||||
opts.method[i] = normalizeAndValidateMethod.call(this, opts.method[i])
|
||||
validateSchemaBodyOption.call(this, opts.method[i], path, opts.schema)
|
||||
|
||||
isGetRoute = opts.method.includes('GET')
|
||||
isHeadRoute = opts.method.includes('HEAD')
|
||||
}
|
||||
} else {
|
||||
opts.method = normalizeAndValidateMethod.call(this, opts.method)
|
||||
validateSchemaBodyOption.call(this, opts.method, path, opts.schema)
|
||||
|
||||
isGetRoute = opts.method === 'GET'
|
||||
isHeadRoute = opts.method === 'HEAD'
|
||||
}
|
||||
|
||||
// we need to clone a set of initial options for HEAD route
|
||||
const headOpts = shouldExposeHead && isGetRoute ? { ...options } : null
|
||||
|
||||
const prefix = this[kRoutePrefix]
|
||||
|
||||
if (path === '/' && prefix.length > 0 && opts.method !== 'HEAD') {
|
||||
@@ -347,19 +349,9 @@ function buildRouting (options) {
|
||||
isFastify
|
||||
})
|
||||
|
||||
if (opts.version) {
|
||||
FSTDEP008()
|
||||
constraints.version = opts.version
|
||||
}
|
||||
|
||||
const headHandler = router.findRoute('HEAD', opts.url, constraints)
|
||||
const hasHEADHandler = headHandler !== null
|
||||
|
||||
// remove the head route created by fastify
|
||||
if (isHeadRoute && hasHEADHandler && !context[kRouteByFastify] && headHandler.store[kRouteByFastify]) {
|
||||
router.off('HEAD', opts.url, constraints)
|
||||
}
|
||||
|
||||
try {
|
||||
router.on(opts.method, opts.url, { constraints }, routeHandler, context)
|
||||
} catch (error) {
|
||||
@@ -377,13 +369,16 @@ function buildRouting (options) {
|
||||
|
||||
this.after((notHandledErr, done) => {
|
||||
// Send context async
|
||||
context.errorHandler = opts.errorHandler ? buildErrorHandler(this[kErrorHandler], opts.errorHandler) : this[kErrorHandler]
|
||||
context.errorHandler = opts.errorHandler
|
||||
? buildErrorHandler(this[kErrorHandler], opts.errorHandler)
|
||||
: this[kErrorHandler]
|
||||
context._parserOptions.limit = opts.bodyLimit || null
|
||||
context.logLevel = opts.logLevel
|
||||
context.logSerializers = opts.logSerializers
|
||||
context.attachValidation = opts.attachValidation
|
||||
context[kReplySerializerDefault] = this[kReplySerializerDefault]
|
||||
context.schemaErrorFormatter = opts.schemaErrorFormatter || this[kSchemaErrorFormatter] || context.schemaErrorFormatter
|
||||
context.schemaErrorFormatter =
|
||||
opts.schemaErrorFormatter || this[kSchemaErrorFormatter] || context.schemaErrorFormatter
|
||||
|
||||
// Run hooks and more
|
||||
avvio.once('preReady', () => {
|
||||
@@ -407,15 +402,24 @@ function buildRouting (options) {
|
||||
fourOhFour.setContext(this, context)
|
||||
|
||||
if (opts.schema) {
|
||||
context.schema = normalizeSchema(opts, context.schema, this.initialConfig)
|
||||
context.schema = normalizeSchema(context.schema, this.initialConfig)
|
||||
|
||||
const schemaController = this[kSchemaController]
|
||||
if (!opts.validatorCompiler && (opts.schema.body || opts.schema.headers || opts.schema.querystring || opts.schema.params)) {
|
||||
const hasValidationSchema = opts.schema.body ||
|
||||
opts.schema.headers ||
|
||||
opts.schema.querystring ||
|
||||
opts.schema.params
|
||||
if (!opts.validatorCompiler && hasValidationSchema) {
|
||||
schemaController.setupValidator(this[kOptions])
|
||||
}
|
||||
try {
|
||||
const isCustom = typeof opts?.validatorCompiler === 'function' || schemaController.isCustomValidatorCompiler
|
||||
compileSchemasForValidation(context, opts.validatorCompiler || schemaController.validatorCompiler, isCustom)
|
||||
const isCustom = typeof opts?.validatorCompiler === 'function' ||
|
||||
schemaController.isCustomValidatorCompiler
|
||||
compileSchemasForValidation(
|
||||
context,
|
||||
opts.validatorCompiler || schemaController.validatorCompiler,
|
||||
isCustom
|
||||
)
|
||||
} catch (error) {
|
||||
throw new FST_ERR_SCH_VALIDATION_BUILD(opts.method, url, error.message)
|
||||
}
|
||||
@@ -440,8 +444,6 @@ function buildRouting (options) {
|
||||
if (shouldExposeHead && isGetRoute && !isHeadRoute && !hasHEADHandler) {
|
||||
const onSendHandlers = parseHeadOnSendHandlers(headOpts.onSend)
|
||||
prepareRoute.call(this, { method: 'HEAD', url: path, options: { ...headOpts, onSend: onSendHandlers }, isFastify: true })
|
||||
} else if (hasHEADHandler && exposeHeadRoute) {
|
||||
FSTDEP007()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -458,20 +460,8 @@ function buildRouting (options) {
|
||||
loggerOpts.serializers = context.logSerializers
|
||||
}
|
||||
const childLogger = createChildLogger(context, logger, req, id, loggerOpts)
|
||||
childLogger[kDisableRequestLogging] = disableRequestLogging
|
||||
|
||||
// TODO: The check here should be removed once https://github.com/nodejs/node/issues/43115 resolve in core.
|
||||
if (!validateHTTPVersion(req.httpVersion)) {
|
||||
childLogger.info({ res: { statusCode: 505 } }, 'request aborted - invalid HTTP version')
|
||||
const message = '{"error":"HTTP Version Not Supported","message":"HTTP Version Not Supported","statusCode":505}'
|
||||
const headers = {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Length': message.length
|
||||
}
|
||||
res.writeHead(505, headers)
|
||||
res.end(message)
|
||||
return
|
||||
}
|
||||
// Set initial value; will be re-evaluated after FastifyRequest is constructed if it's a function
|
||||
childLogger[kDisableRequestLogging] = disableRequestLoggingFn ? false : disableRequestLogging
|
||||
|
||||
if (closing === true) {
|
||||
/* istanbul ignore next mac, windows */
|
||||
@@ -515,7 +505,15 @@ function buildRouting (options) {
|
||||
|
||||
const request = new context.Request(id, params, req, query, childLogger, context)
|
||||
const reply = new context.Reply(res, request, childLogger)
|
||||
if (disableRequestLogging === false) {
|
||||
|
||||
// Evaluate disableRequestLogging after FastifyRequest is constructed
|
||||
// so the caller has access to decorations and customizations
|
||||
const resolvedDisableRequestLogging = disableRequestLoggingFn
|
||||
? disableRequestLoggingFn(request)
|
||||
: disableRequestLogging
|
||||
childLogger[kDisableRequestLogging] = resolvedDisableRequestLogging
|
||||
|
||||
if (resolvedDisableRequestLogging === false) {
|
||||
childLogger.info({ req: request }, 'incoming request')
|
||||
}
|
||||
|
||||
@@ -577,7 +575,8 @@ function normalizeAndValidateMethod (method) {
|
||||
throw new FST_ERR_ROUTE_METHOD_INVALID()
|
||||
}
|
||||
method = method.toUpperCase()
|
||||
if (supportedMethods.indexOf(method) === -1) {
|
||||
if (!this[kSupportedHTTPMethods].bodyless.has(method) &&
|
||||
!this[kSupportedHTTPMethods].bodywith.has(method)) {
|
||||
throw new FST_ERR_ROUTE_METHOD_NOT_SUPPORTED(method)
|
||||
}
|
||||
|
||||
@@ -585,7 +584,7 @@ function normalizeAndValidateMethod (method) {
|
||||
}
|
||||
|
||||
function validateSchemaBodyOption (method, path, schema) {
|
||||
if ((method === 'GET' || method === 'HEAD') && schema && schema.body) {
|
||||
if (this[kSupportedHTTPMethods].bodyless.has(method) && schema?.body) {
|
||||
throw new FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED(method, path)
|
||||
}
|
||||
}
|
||||
@@ -608,12 +607,30 @@ function runPreParsing (err, request, reply) {
|
||||
request[kRequestPayloadStream] = request.raw
|
||||
|
||||
if (request[kRouteContext].preParsing !== null) {
|
||||
preParsingHookRunner(request[kRouteContext].preParsing, request, reply, handleRequest)
|
||||
preParsingHookRunner(request[kRouteContext].preParsing, request, reply, handleRequest.bind(request.server))
|
||||
} else {
|
||||
handleRequest(null, request, reply)
|
||||
handleRequest.call(request.server, null, request, reply)
|
||||
}
|
||||
}
|
||||
|
||||
function buildRouterOptions (options, defaultOptions) {
|
||||
const routerOptions = options.routerOptions || Object.create(null)
|
||||
|
||||
const usedDeprecatedOptions = routerKeys.filter(key => Object.hasOwn(options, key))
|
||||
|
||||
if (usedDeprecatedOptions.length > 0) {
|
||||
FSTDEP022(usedDeprecatedOptions.join(', '))
|
||||
}
|
||||
|
||||
for (const key of routerKeys) {
|
||||
if (!Object.hasOwn(routerOptions, key)) {
|
||||
routerOptions[key] = options[key] ?? defaultOptions[key]
|
||||
}
|
||||
}
|
||||
|
||||
return routerOptions
|
||||
}
|
||||
|
||||
/**
|
||||
* Used within the route handler as a `net.Socket.close` event handler.
|
||||
* The purpose is to remove a socket from the tracked sockets collection when
|
||||
@@ -625,4 +642,4 @@ function removeTrackedSocket () {
|
||||
|
||||
function noop () { }
|
||||
|
||||
module.exports = { buildRouting, validateBodyLimitOption }
|
||||
module.exports = { buildRouting, validateBodyLimitOption, buildRouterOptions }
|
||||
|
||||
Reference in New Issue
Block a user