/
home
/
infinitibizsol
/
testingcrm.infinitibizsol.com
/
node_modules
/
fastify
/
lib
/
File Upload :
llllll
Current File: /home/infinitibizsol/testingcrm.infinitibizsol.com/node_modules/fastify/lib/route.js
'use strict' const FindMyWay = require('find-my-way') const Context = require('./context') const handleRequest = require('./handleRequest') const { hookRunner, hookIterator, lifecycleHooks } = require('./hooks') const supportedMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTIONS'] const { normalizeSchema } = require('./schemas') const { parseHeadOnSendHandlers } = require('./headRoute') const warning = require('./warnings') const { kRequestAcceptVersion } = require('./symbols') const { compileSchemasForValidation, compileSchemasForSerialization } = require('./validation') const { FST_ERR_SCH_VALIDATION_BUILD, FST_ERR_SCH_SERIALIZATION_BUILD, FST_ERR_DEFAULT_ROUTE_INVALID_TYPE, FST_ERR_INVALID_URL } = require('./errors') const { kRoutePrefix, kLogLevel, kLogSerializers, kHooks, kHooksDeprecatedPreParsing, kSchemaController, kOptions, kContentTypeParser, kReply, kReplySerializerDefault, kReplyIsError, kRequest, kRequestPayloadStream, kDisableRequestLogging, kSchemaErrorFormatter, kErrorHandler } = require('./symbols.js') function buildRouting (options) { const { keepAliveConnections } = options const router = FindMyWay(options.config) let avvio let fourOhFour let requestIdHeader let querystringParser let requestIdLogLabel let logger let hasLogger let setupResponseListeners let throwIfAlreadyStarted let genReqId let disableRequestLogging let ignoreTrailingSlash let return503OnClosing let globalExposeHeadRoutes let closing = false return { setup (options, fastifyArgs) { avvio = fastifyArgs.avvio fourOhFour = fastifyArgs.fourOhFour logger = fastifyArgs.logger hasLogger = fastifyArgs.hasLogger setupResponseListeners = fastifyArgs.setupResponseListeners throwIfAlreadyStarted = fastifyArgs.throwIfAlreadyStarted globalExposeHeadRoutes = options.exposeHeadRoutes requestIdHeader = options.requestIdHeader querystringParser = options.querystringParser requestIdLogLabel = options.requestIdLogLabel genReqId = options.genReqId disableRequestLogging = options.disableRequestLogging ignoreTrailingSlash = options.ignoreTrailingSlash return503OnClosing = Object.prototype.hasOwnProperty.call(options, 'return503OnClosing') ? options.return503OnClosing : true }, routing: router.lookup.bind(router), // router func to find the right handler to call route, // configure a route in the fastify instance prepareRoute, getDefaultRoute: function () { return router.defaultRoute }, setDefaultRoute: function (defaultRoute) { if (typeof defaultRoute !== 'function') { throw new FST_ERR_DEFAULT_ROUTE_INVALID_TYPE() } router.defaultRoute = defaultRoute }, routeHandler, closeRoutes: () => { closing = true }, printRoutes: router.prettyPrint.bind(router) } // Convert shorthand to extended route declaration function prepareRoute (method, url, options, handler) { if (typeof url !== 'string') { throw new FST_ERR_INVALID_URL(typeof url) } if (!handler && typeof options === 'function') { handler = options // for support over direct function calls such as fastify.get() options are reused as the handler options = {} } else if (handler && typeof handler === 'function') { if (Object.prototype.toString.call(options) !== '[object Object]') { throw new Error(`Options for ${method}:${url} route must be an object`) } else if (options.handler) { if (typeof options.handler === 'function') { throw new Error(`Duplicate handler for ${method}:${url} route is not allowed!`) } else { throw new Error(`Handler for ${method}:${url} route must be a function`) } } } options = Object.assign({}, options, { method, url, path: url, handler: handler || (options && options.handler) }) return route.call(this, options) } // Route management function route (options) { // Since we are mutating/assigning only top level props, it is fine to have a shallow copy using the spread operator const opts = { ...options } throwIfAlreadyStarted('Cannot add route when fastify instance is already started!') if (Array.isArray(opts.method)) { // eslint-disable-next-line no-var for (var i = 0; i < opts.method.length; ++i) { const method = opts.method[i] if (supportedMethods.indexOf(method) === -1) { throw new Error(`${method} method is not supported!`) } } } else { if (supportedMethods.indexOf(opts.method) === -1) { throw new Error(`${opts.method} method is not supported!`) } } const path = opts.url || opts.path if (!opts.handler) { throw new Error(`Missing handler function for ${opts.method}:${path} route.`) } if (opts.errorHandler !== undefined && typeof opts.errorHandler !== 'function') { throw new Error(`Error Handler for ${opts.method}:${path} route, if defined, must be a function`) } validateBodyLimitOption(opts.bodyLimit) const prefix = this[kRoutePrefix] this.after((notHandledErr, done) => { if (path === '/' && prefix.length && opts.method !== 'HEAD') { switch (opts.prefixTrailingSlash) { case 'slash': afterRouteAdded.call(this, { path }, notHandledErr, done) break case 'no-slash': afterRouteAdded.call(this, { path: '' }, notHandledErr, done) break case 'both': default: afterRouteAdded.call(this, { path: '' }, notHandledErr, done) // If ignoreTrailingSlash is set to true we need to add only the '' route to prevent adding an incomplete one. if (ignoreTrailingSlash !== true) { afterRouteAdded.call(this, { path, prefixing: true }, notHandledErr, done) } } } else if (path && path[0] === '/' && prefix.endsWith('/')) { // Ensure that '/prefix/' + '/route' gets registered as '/prefix/route' afterRouteAdded.call(this, { path: path.slice(1) }, notHandledErr, done) } else { afterRouteAdded.call(this, { path }, notHandledErr, done) } }) // chainable api return this /** * This function sets up a new route, its log serializers, and triggers route hooks. * * @param {object} opts contains route `path` and `prefixing` flag which indicates if this is an auto-prefixed route, e.g. `fastify.register(routes, { prefix: '/foo' })` * @param {*} notHandledErr error object to be passed back to the original invoker * @param {*} done callback */ function afterRouteAdded ({ path, prefixing = false }, notHandledErr, done) { const url = prefix + path opts.url = url opts.path = url opts.routePath = path opts.prefix = prefix opts.logLevel = opts.logLevel || this[kLogLevel] if (this[kLogSerializers] || opts.logSerializers) { opts.logSerializers = Object.assign(Object.create(this[kLogSerializers]), opts.logSerializers) } if (opts.attachValidation == null) { opts.attachValidation = false } if (prefixing === false) { // run 'onRoute' hooks for (const hook of this[kHooks].onRoute) { try { hook.call(this, opts) } catch (error) { done(error) return } } } const config = { ...opts.config, url, method: opts.method } const constraints = opts.constraints || {} if (opts.version) { warning.emit('FSTDEP008') constraints.version = opts.version } const context = new Context( opts.schema, opts.handler.bind(this), this[kReply], this[kRequest], this[kContentTypeParser], config, opts.errorHandler || this[kErrorHandler], opts.bodyLimit, opts.logLevel, opts.logSerializers, opts.attachValidation, this[kReplySerializerDefault], opts.schemaErrorFormatter || this[kSchemaErrorFormatter] ) const headRouteExists = router.find('HEAD', url, constraints) != null try { router.on(opts.method, opts.url, { constraints }, routeHandler, context) } catch (err) { done(err) return } const { exposeHeadRoute } = opts const hasRouteExposeHeadRouteFlag = exposeHeadRoute != null const shouldExposeHead = hasRouteExposeHeadRouteFlag ? exposeHeadRoute : globalExposeHeadRoutes if (shouldExposeHead && options.method === 'GET' && !headRouteExists) { const onSendHandlers = parseHeadOnSendHandlers(opts.onSend) prepareRoute.call(this, 'HEAD', path, { ...opts, onSend: onSendHandlers }) } else if (headRouteExists && exposeHeadRoute) { warning.emit('FSTDEP007') } // It can happen that a user registers a plugin with some hooks *after* // the route registration. To be sure to also load those hooks, // we must listen for the avvio's preReady event, and update the context object accordingly. avvio.once('preReady', () => { for (const hook of lifecycleHooks) { const toSet = this[kHooks][hook] .concat(opts[hook] || []) .map(h => { const bound = h.bind(this) // Track hooks deprecation markers if (hook === 'preParsing') { // Check for deprecation syntax if (h.length === (h.constructor.name === 'AsyncFunction' ? 2 : 3)) { warning.emit('FSTDEP004') bound[kHooksDeprecatedPreParsing] = true } } return bound }) context[hook] = toSet.length ? toSet : null } // Must store the 404 Context in 'preReady' because it is only guaranteed to // be available after all of the plugins and routes have been loaded. fourOhFour.setContext(this, context) if (opts.schema) { 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)) { schemaController.setupValidator(this[kOptions]) } try { compileSchemasForValidation(context, opts.validatorCompiler || schemaController.validatorCompiler) } catch (error) { throw new FST_ERR_SCH_VALIDATION_BUILD(opts.method, url, error.message) } if (opts.schema.response && !opts.serializerCompiler) { schemaController.setupSerializer(this[kOptions]) } try { compileSchemasForSerialization(context, opts.serializerCompiler || schemaController.serializerCompiler) } catch (error) { throw new FST_ERR_SCH_SERIALIZATION_BUILD(opts.method, url, error.message) } } }) done(notHandledErr) } } // HTTP request entry point, the routing has already been executed function routeHandler (req, res, params, context) { if (closing === true) { /* istanbul ignore next mac, windows */ if (req.httpVersionMajor !== 2) { res.once('finish', () => req.destroy()) res.setHeader('Connection', 'close') } if (return503OnClosing) { const headers = { 'Content-Type': 'application/json', 'Content-Length': '80' } res.writeHead(503, headers) res.end('{"error":"Service Unavailable","message":"Service Unavailable","statusCode":503}') return } } // When server.forceCloseConnections is true, we will collect any requests // that have indicated they want persistence so that they can be reaped // on server close. Otherwise, the container is a noop container. const connHeader = String.prototype.toLowerCase.call(req.headers.connection || '') if (connHeader === 'keep-alive') { if (keepAliveConnections.has(req.socket) === false) { keepAliveConnections.add(req.socket) req.socket.on('close', removeTrackedSocket.bind({ keepAliveConnections, socket: req.socket })) } } // we revert the changes in defaultRoute if (req.headers[kRequestAcceptVersion] !== undefined) { req.headers['accept-version'] = req.headers[kRequestAcceptVersion] req.headers[kRequestAcceptVersion] = undefined } const id = req.headers[requestIdHeader] || genReqId(req) const loggerBinding = { [requestIdLogLabel]: id } const loggerOpts = { level: context.logLevel } if (context.logSerializers) { loggerOpts.serializers = context.logSerializers } const childLogger = logger.child(loggerBinding, loggerOpts) childLogger[kDisableRequestLogging] = disableRequestLogging const queryPrefix = req.url.indexOf('?') const query = querystringParser(queryPrefix > -1 ? req.url.slice(queryPrefix + 1) : '') const request = new context.Request(id, params, req, query, childLogger, context) const reply = new context.Reply(res, request, childLogger) if (disableRequestLogging === false) { childLogger.info({ req: request }, 'incoming request') } if (hasLogger === true || context.onResponse !== null) { setupResponseListeners(reply) } if (context.onRequest !== null) { hookRunner( context.onRequest, hookIterator, request, reply, runPreParsing ) } else { runPreParsing(null, request, reply) } if (context.onTimeout !== null) { if (!request.raw.socket._meta) { request.raw.socket.on('timeout', handleTimeout) } request.raw.socket._meta = { context, request, reply } } } } function handleTimeout () { const { context, request, reply } = this._meta hookRunner( context.onTimeout, hookIterator, request, reply, noop ) } function validateBodyLimitOption (bodyLimit) { if (bodyLimit === undefined) return if (!Number.isInteger(bodyLimit) || bodyLimit <= 0) { throw new TypeError(`'bodyLimit' option must be an integer > 0. Got '${bodyLimit}'`) } } function runPreParsing (err, request, reply) { if (reply.sent === true) return if (err != null) { reply.send(err) return } request[kRequestPayloadStream] = request.raw if (reply.context.preParsing !== null) { preParsingHookRunner(reply.context.preParsing, request, reply, handleRequest) } else { handleRequest(null, request, reply) } } function preParsingHookRunner (functions, request, reply, cb) { let i = 0 function next (err, stream) { if (reply.sent) { return } if (typeof stream !== 'undefined') { request[kRequestPayloadStream] = stream } if (err || i === functions.length) { if (err && !(err instanceof Error)) { reply[kReplyIsError] = true } cb(err, request, reply) return } const fn = functions[i++] let result try { if (fn[kHooksDeprecatedPreParsing]) { result = fn(request, reply, next) } else { result = fn(request, reply, request[kRequestPayloadStream], next) } } catch (error) { next(error) return } if (result && typeof result.then === 'function') { result.then(handleResolve, handleReject) } } function handleResolve (stream) { next(null, stream) } function handleReject (err) { next(err) } next(null, request[kRequestPayloadStream]) } /** * 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 * the socket has naturally timed out. */ function removeTrackedSocket () { this.keepAliveConnections.delete(this.socket) } function noop () { } module.exports = { buildRouting, validateBodyLimitOption }
Copyright ©2k19 -
Hexid
|
Tex7ure