@halsp/http
Version:
支持 Halsp HTTP 请求
166 lines • 6.01 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.parsePattern = exports.MapMatcher = void 0;
const core_1 = require("@halsp/core");
const methods_1 = require("./methods.cjs");
class MapMatcher {
ctx;
options;
constructor(ctx, options) {
this.ctx = ctx;
this.options = options;
this.#parsedRegisters = ctx.startup.parsedRegisters;
}
#parsedRegisters;
async match() {
const register = this.getRegister();
if (!register)
return;
parseParams(this.ctx, register);
if (register.handler) {
await register.handler(this.ctx);
}
}
getRegister() {
const matchedPaths = this.#parsedRegisters
.filter((r) => !!r.methods.length)
.filter((r) => this.isPathMatched(r, true));
this.#parsedRegisters
.filter((r) => !r.methods.length || r.methods.includes(methods_1.HttpMethods.any))
.filter((m) => this.isPathMatched(m, false))
.forEach((m) => matchedPaths.push(m));
const mapItem = this.getMostLikeRegister(matchedPaths);
if (mapItem)
return mapItem;
const otherMethodPathCount = this.#parsedRegisters.filter((r) => this.isPathMatched(r, false)).length;
if (otherMethodPathCount) {
const method = this.ctx.req.method;
this.ctx.res.methodNotAllowedMsg({
message: `method not allowed:${method}`,
method: method,
path: this.ctx.req.path,
});
}
else {
this.ctx.res.notFoundMsg({
message: `Can't find the path:${this.ctx.req.path}`,
path: this.ctx.req.path,
});
}
}
isPathMatched(register, methodIncluded) {
const reqUrl = this.ctx.req.path;
const reqUrlStrs = reqUrl
.toLowerCase()
.split("/")
.filter((item) => !!item);
const mapUrlStrs = register.url
.toLowerCase()
.split("/")
.filter((item) => !!item);
if (reqUrlStrs.length != mapUrlStrs.length)
return false;
if (methodIncluded && !register.methods.includes(methods_1.HttpMethods.any)) {
const matchedMethod = methods_1.HttpMethods.matched(this.ctx.req.method, this.options.customMethods);
if (!matchedMethod || !register.methods.includes(matchedMethod)) {
return false;
}
}
for (let i = 0; i < mapUrlStrs.length; i++) {
if (mapUrlStrs[i] != reqUrlStrs[i] && !mapUrlStrs[i].startsWith("^")) {
return false;
}
}
return true;
}
getMostLikeRegister(registers) {
if (!registers || !registers.length)
return;
if (registers.length == 1)
return registers[0];
const pathsParts = [];
registers.forEach((register) => {
pathsParts.push({
register: register,
parts: register.url
.toLowerCase()
.split("/")
.filter((item) => !!item),
});
});
const minPartsCount = Math.min(...pathsParts.map((pp) => pp.parts.length));
for (let i = 0; i < minPartsCount; i++) {
if (pathsParts.some((p) => p.parts[i].includes("^")) &&
pathsParts.some((p) => !p.parts[i].includes("^"))) {
pathsParts
.filter((p) => p.parts[i].includes("^"))
.forEach((p) => pathsParts.splice(pathsParts.indexOf(p), 1));
}
if (pathsParts.length == 1)
return pathsParts[0].register;
}
if (pathsParts.some((pp) => pp.register.methods.includes(methods_1.HttpMethods.any)) &&
pathsParts.some((pp) => !pp.register.methods.includes(methods_1.HttpMethods.any))) {
pathsParts
.filter((pp) => pp.register.methods.includes(methods_1.HttpMethods.any))
.forEach((pp) => {
pathsParts.splice(pathsParts.indexOf(pp), 1);
});
}
return pathsParts.sort((a, b) => a.parts.length - b.parts.length)[0]
.register;
}
}
exports.MapMatcher = MapMatcher;
function parsePattern(register) {
const strs = register.pattern.trim().split("//");
if (strs.length <= 1) {
return {
methods: [],
url: (0, core_1.normalizePath)(strs[0]),
handler: register.handler,
};
}
else {
return {
methods: strs[0]
.split(",")
.filter((m) => !!m)
.map((m) => m.toUpperCase()),
url: (0, core_1.normalizePath)(strs[1]),
handler: register.handler,
};
}
}
exports.parsePattern = parsePattern;
function parseParams(ctx, register) {
const params = {};
if (register.url.includes("^")) {
const mapPathStrs = register.url.split("/").filter((item) => !!item);
const reqPathStrs = ctx.req.path.split("/").filter((item) => !!item);
for (let i = 0; i < Math.min(mapPathStrs.length, reqPathStrs.length); i++) {
const mapPathStr = mapPathStrs[i];
if (!mapPathStr.startsWith("^"))
continue;
const reqPathStr = reqPathStrs[i];
const key = mapPathStr.substring(1, mapPathStr.length);
const value = decodeURIComponent(reqPathStr);
params[key] = value;
}
}
Object.defineProperty(ctx.req, "params", {
configurable: true,
enumerable: true,
get: () => {
return params;
},
});
Object.defineProperty(ctx.req, "param", {
configurable: true,
enumerable: true,
get: () => {
return params;
},
});
}
//# sourceMappingURL=map-matcher.js.map
;