* Route management * @param {{ options: import('../fastify').RouteOptions, isFastify: boolean }}
({ options, isFastify })
| 208 | * @param {{ options: import('../fastify').RouteOptions, isFastify: boolean }} |
| 209 | */ |
| 210 | function route ({ options, isFastify }) { |
| 211 | throwIfAlreadyStarted('Cannot add route!') |
| 212 | |
| 213 | // Since we are mutating/assigning only top level props, it is fine to have a shallow copy using the spread operator |
| 214 | const opts = { ...options } |
| 215 | |
| 216 | const path = opts.url || opts.path || '' |
| 217 | |
| 218 | if (!opts.handler) { |
| 219 | throw new FST_ERR_ROUTE_MISSING_HANDLER(opts.method, path) |
| 220 | } |
| 221 | |
| 222 | if (opts.errorHandler !== undefined && typeof opts.errorHandler !== 'function') { |
| 223 | throw new FST_ERR_ROUTE_HANDLER_NOT_FN(opts.method, path) |
| 224 | } |
| 225 | |
| 226 | validateBodyLimitOption(opts.bodyLimit) |
| 227 | validateHandlerTimeoutOption(opts.handlerTimeout) |
| 228 | |
| 229 | const shouldExposeHead = opts.exposeHeadRoute ?? globalExposeHeadRoutes |
| 230 | |
| 231 | let isGetRoute = false |
| 232 | let isHeadRoute = false |
| 233 | |
| 234 | if (Array.isArray(opts.method)) { |
| 235 | for (let i = 0; i < opts.method.length; ++i) { |
| 236 | opts.method[i] = normalizeAndValidateMethod.call(this, opts.method[i]) |
| 237 | validateSchemaBodyOption.call(this, opts.method[i], path, opts.schema) |
| 238 | |
| 239 | isGetRoute = opts.method.includes('GET') |
| 240 | isHeadRoute = opts.method.includes('HEAD') |
| 241 | } |
| 242 | } else { |
| 243 | opts.method = normalizeAndValidateMethod.call(this, opts.method) |
| 244 | validateSchemaBodyOption.call(this, opts.method, path, opts.schema) |
| 245 | |
| 246 | isGetRoute = opts.method === 'GET' |
| 247 | isHeadRoute = opts.method === 'HEAD' |
| 248 | } |
| 249 | |
| 250 | // we need to clone a set of initial options for HEAD route |
| 251 | const headOpts = shouldExposeHead && isGetRoute ? { ...options } : null |
| 252 | |
| 253 | const prefix = this[kRoutePrefix] |
| 254 | |
| 255 | if (path === '/' && prefix.length > 0 && opts.method !== 'HEAD') { |
| 256 | switch (opts.prefixTrailingSlash) { |
| 257 | case 'slash': |
| 258 | addNewRoute.call(this, { path, isFastify }) |
| 259 | break |
| 260 | case 'no-slash': |
| 261 | addNewRoute.call(this, { path: '', isFastify }) |
| 262 | break |
| 263 | case 'both': |
| 264 | default: |
| 265 | addNewRoute.call(this, { path: '', isFastify }) |
| 266 | // If ignoreTrailingSlash is set to true we need to add only the '' route to prevent adding an incomplete one. |
| 267 | if (ignoreTrailingSlash !== true && (ignoreDuplicateSlashes !== true || !prefix.endsWith('/'))) { |
nothing calls this directly
no test coverage detected