UNPKG

actionhero

Version:

actionhero.js is a multi-transport API Server with integrated cluster capabilities and delayed tasks

168 lines (167 loc) 7.67 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Routes = void 0; const path = require("path"); const index_1 = require("../index"); /** * Contains routing options for web clients. Can associate routes with actions or files. */ class Routes extends index_1.Initializer { constructor() { super(); this.name = "routes"; this.loadPriority = 500; } async initialize(config) { index_1.api.routes = { routes: {}, verbs: ["head", "get", "post", "put", "patch", "delete"], }; index_1.api.routes.processRoute = (connection, pathParts) => { if (connection.params.action === undefined || index_1.api.actions.actions[connection.params.action] === undefined) { let method = connection.rawConnection.method.toLowerCase(); if (method === "head" && !index_1.api.routes.routes.head) { method = "get"; } for (const i in index_1.api.routes.routes[method]) { const route = index_1.api.routes.routes[method][i]; const match = index_1.api.routes.matchURL(pathParts, route.path, route.matchTrailingPathParts); if (match.match === true) { if (route.apiVersion) { connection.params.apiVersion = connection.params.apiVersion || route.apiVersion; } for (const param in match.params) { try { const decodedName = decodeURIComponent(param.replace(/\+/g, " ")); const decodedValue = decodeURIComponent(match.params[param].replace(/\+/g, " ")); connection.params[decodedName] = decodedValue; } catch (e) { // malformed URL } } connection.matchedRoute = route; if (route.dir) { const requestedFile = connection.rawConnection.parsedURL.pathname.substring(route.path.length, connection.rawConnection.parsedURL.pathname.length); connection.params.file = path.normalize(route.dir + "/" + requestedFile); } else { connection.params.action = route.action; } break; } } } }; index_1.api.routes.matchURL = (pathParts, match, matchTrailingPathParts) => { const response = { match: false, params: {} }; const matchParts = match.split("/"); let regexp = ""; let variable = ""; if (matchParts[0] === "") { matchParts.splice(0, 1); } if (matchParts[matchParts.length - 1] === "") { matchParts.pop(); } if (matchParts.length !== pathParts.length && matchTrailingPathParts !== true) { return response; } for (const i in matchParts) { const matchPart = matchParts[i]; let pathPart = pathParts[i]; if (matchTrailingPathParts === true && parseInt(i) === matchParts.length - 1) { for (const j in pathParts) { if (j > i) { pathPart = pathPart + "/" + pathParts[j]; } } } if (!pathPart) { return response; } if (matchPart.indexOf(":") >= 0) { const trimmedMatchParts = matchPart.split(":"); const trimmedMatchPart = trimmedMatchParts[trimmedMatchParts.length - 1]; const replacement = trimmedMatchParts[trimmedMatchParts.length - 2]; if (replacement) { pathPart = pathPart.replace(replacement, ""); } if (trimmedMatchPart.indexOf("(") < 0) { variable = trimmedMatchPart; response.params[variable] = pathPart; } else { variable = trimmedMatchPart.replace(":", "").split("(")[0]; regexp = trimmedMatchPart.substring(trimmedMatchPart.indexOf("(") + 1, trimmedMatchPart.length - 1); const matches = pathPart.match(new RegExp(regexp, "g")); if (matches) { response.params[variable] = pathPart; } else { return response; } } } else { if (pathPart === null || pathPart === undefined || pathParts[i].toLowerCase() !== matchPart.toLowerCase()) { return response; } } } response.match = true; return response; }; // load in the routes file index_1.api.routes.loadRoutes = (rawRoutes) => { let counter = 0; index_1.api.routes.verbs.forEach((verb) => { index_1.api.routes.routes[verb] = index_1.api.routes.routes[verb] || []; }); if (!rawRoutes) { if (config.routes) { rawRoutes = config.routes; } } let v; let verb; for (const i in rawRoutes) { const method = i.toLowerCase(); for (const j in rawRoutes[i]) { const thisRoute = rawRoutes[i][j]; if (method === "all") { for (v in index_1.api.routes.verbs) { verb = index_1.api.routes.verbs[v]; index_1.route.registerRoute(verb, thisRoute.path, thisRoute.action, thisRoute.apiVersion, thisRoute.matchTrailingPathParts, thisRoute.dir); } } else { index_1.route.registerRoute(method, thisRoute.path, thisRoute.action, thisRoute.apiVersion, thisRoute.matchTrailingPathParts, thisRoute.dir); } counter++; } } index_1.api.params.postVariables = index_1.utils.arrayUnique(index_1.api.params.postVariables); if (config.servers.web && config.servers.web.simpleRouting === true) { const simplePaths = []; for (const action in index_1.api.actions.actions) { simplePaths.push("/" + action); for (v in index_1.api.routes.verbs) { verb = index_1.api.routes.verbs[v]; index_1.route.registerRoute(verb, "/" + action, action, null); } } index_1.log(`${simplePaths.length} simple routes loaded from action names`, "debug"); index_1.log("routes:", "debug", index_1.api.routes.routes); } }; index_1.api.routes.loadRoutes(); } } exports.Routes = Routes;