UNPKG

rjweb-server

Version:

Easy and Robust Way to create a Web Server with Many Easy-to-use Features in NodeJS

175 lines (174 loc) 5.01 kB
import parsePath from "../functions/parsePath"; import { isRegExp } from "util/types"; class Path { /** * Create a new Path object * @since 8.4.0 */ constructor(method, path) { this.method = method; this.path = path; if (isRegExp(path)) { this.data = { type: "regexp", value: path, prefix: "/", segments: [{ raw: "", paramsRegExp: new RegExp(""), params: [] }, { raw: "", paramsRegExp: new RegExp(""), params: [] }] }; } else if (typeof path === "string") { const segments = parsePath(path).split("/"); this.data = { type: "normal", value: segments.join("/"), segments: [] }; for (const segment of segments) { this.data.segments.push({ raw: segment, paramsRegExp: new RegExp(segment.replace(/{([^}]+)}/g, "(.*)")), params: (segment.match(/{([^}]+)}/g) ?? []).map((m) => m.slice(1, -1)) }); } } else { throw new Error(`Invalid Path (${typeof path})`); } } /** * Add a Prefix to the Path * @since 8.4.0 */ addPrefix(prefix) { switch (this.data.type) { case "normal": { const segments = parsePath([prefix, this.data.value]).split("/"); this.path = segments.join("/"); this.data = { type: "normal", value: segments.join("/"), segments: [] }; for (const segment of segments) { this.data.segments.push({ raw: segment, paramsRegExp: new RegExp(segment.replace(/{([^}]+)}/g, "(.*)")), params: (segment.match(/{([^}]+)}/g) ?? []).map((m) => m.slice(1, -1)) }); } break; } case "regexp": { const segments = parsePath([prefix, this.data.prefix]).split("/"); this.data = { type: "regexp", value: this.data.value, prefix: segments.join("/"), segments: [] }; for (const segment of segments) { this.data.segments.push({ raw: segment, paramsRegExp: new RegExp(segment.replace(/{([^}]+)}/g, "(.*)")), params: (segment.match(/{([^}]+)}/g) ?? []).map((m) => m.slice(1, -1)) }); } break; } } return this; } /** * Add a Suffix to the Path * @since 8.4.0 */ addSuffix(prefix) { switch (this.data.type) { case "normal": { const segments = parsePath([this.data.value, prefix]).split("/"); this.path = segments.join("/"); this.data = { type: "normal", value: segments.join("/"), segments: [] }; for (const segment of segments) { this.data.segments.push({ raw: segment, paramsRegExp: new RegExp(segment.replace(/{([^}]+)}/g, "(.*)")), params: (segment.match(/{([^}]+)}/g) ?? []).map((m) => m.slice(1, -1)) }); } break; } case "regexp": { const segments = parsePath([this.data.prefix, prefix]).split("/"); this.data = { type: "regexp", value: this.data.value, prefix: segments.join("/"), segments: [] }; for (const segment of segments) { this.data.segments.push({ raw: segment, paramsRegExp: new RegExp(segment.replace(/{([^}]+)}/g, "(.*)")), params: (segment.match(/{([^}]+)}/g) ?? []).map((m) => m.slice(1, -1)) }); } break; } } return this; } /** * Test the Path against the Request Path * @since 8.4.0 */ matches(method, collection, requestPath, requestPathSplit) { if (this.method !== method) return false; if (this.data.type === "normal" && this.data.segments.length !== requestPathSplit.length) return false; if (this.data.type === "regexp" && !this.data.value.test(parsePath(requestPath.replace(this.data.prefix, "")))) return false; let found = false; for (let i = 1; i < requestPathSplit.length; i++) { const reqSegment = requestPathSplit[i], segment = this.data.segments[i]; if (!segment) { if (this.data.type === "normal") break; found = true; break; } if (segment.params.length === 0) { if (segment.raw === reqSegment) { if (i === requestPathSplit.length - 1 && this.data.type === "normal") { found = true; break; } } else break; } const params = reqSegment.match(segment.paramsRegExp); if (params) { if (i === requestPathSplit.length) found = true; for (let i2 = 0; i2 < segment.params.length; i2++) { collection.set(segment.params[i2], params[i2 + 1]); } } else break; } return found; } } export { Path as default };