nralcm
Version:
This is a framework based on NodeJs to manage rest api request lifecycle
118 lines (117 loc) • 5.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
require("reflect-metadata");
const __1 = require("..");
const exceptions_1 = require("../../exceptions");
/**
* Maps current request with api method of controller
* @param context HttpContext object
* @returns RouteDescriptor object, If not found throws NotFoundException
*/
function ApiMethodMapper(context, restApiConfiguration) {
const urlParts = getUrlParts(context.request.url);
const url = urlParts.slice(1).join("/");
// try to find route without param
const routeDescriptors = Reflect.getMetadata("routes", context.controllerObject);
const routeDescriptor = routeDescriptors.find(routeDescriptor => {
return context.request.method.toLowerCase() === routeDescriptor.httpMethod.toLowerCase()
&& (!url ? (routeDescriptor.methodName.toUpperCase() === context.request.method.toUpperCase()) :
routeDescriptor.route === url);
});
if (routeDescriptor) {
mapQueryString(context, routeDescriptor);
return routeDescriptor;
}
// find route with param
const paramMapResult = mapParams(context, routeDescriptors, url);
if (paramMapResult !== null) {
mapQueryString(context, paramMapResult);
return paramMapResult;
}
throw new exceptions_1.NotFoundException();
}
exports.ApiMethodMapper = ApiMethodMapper;
/**
* get url parts after api
* @param url request url
* @returns Array of url parts
*/
function getUrlParts(url) {
url = url.substring(url.indexOf("api") + 3);
url = url.startsWith("/") ? url.substring(1) : url;
const queryStringIndex = url.indexOf("?");
if (queryStringIndex > 0) {
url = url.substring(0, url.indexOf("?"));
}
return url ? url.split("/") : [];
}
/**
* Maps params of url with route and saves in meta data of controller object
* @param context HttpContext Object
* @param routeDescriptors All RouteDescriptor data of controller
* @param url compact url like compact url of 'api/product/getproduct' will be getproduct
*/
function mapParams(context, routeDescriptors, url) {
for (let index = 0; index < routeDescriptors.length; index++) {
const routeDescriptor = routeDescriptors[index];
routeDescriptor.route = routeDescriptor.route || "/";
const routeParts = routeDescriptor.route.startsWith("/") ?
routeDescriptor.route.substring(1).split("/") : routeDescriptor.route.split("/");
const urlParts = url.startsWith("/") ? url.substring(1).split("/") : url.split("/");
if (routeParts.length === urlParts.length && routeDescriptor.route.indexOf("{") >= 0 && routeDescriptor.route.indexOf("}") >= 0) {
const nonParamsRouteParts = routeParts.filter(route => route.indexOf("{") === -1 || route.indexOf("}") === -1);
let isMatched = false;
nonParamsRouteParts.forEach((routePart) => {
if (urlParts.find(urlPart => urlPart === routePart)) {
isMatched = true;
}
else {
isMatched = false;
}
});
if (isMatched || nonParamsRouteParts.length === 0) {
isMatched = true;
routeParts.forEach((route, i) => {
const openCurlyBraceIndex = route.indexOf("{");
const closeCurlyBraceIndex = route.indexOf("}");
if (openCurlyBraceIndex >= 0 && closeCurlyBraceIndex >= 0) {
if (urlParts[i]) {
const paramData = {
paramName: route.substring(openCurlyBraceIndex + 1, closeCurlyBraceIndex),
paramValue: urlParts[i]
};
const paramMetaDataArr = Reflect.getMetadata(__1.Constants.metadata.routeParams, context.controllerObject, routeDescriptors[index].methodName) || [];
paramMetaDataArr.push(paramData);
Reflect.defineMetadata(__1.Constants.metadata.routeParams, paramMetaDataArr, context.controllerObject, routeDescriptors[index].methodName);
}
else {
const existingErrorMessages = Reflect.getMetadata(__1.Constants.metadata.emptyRouteParams, context.controllerObject) || [];
existingErrorMessages.push(`Parametr ${route.substring(openCurlyBraceIndex + 1, closeCurlyBraceIndex)} is missing`);
Reflect.defineMetadata(__1.Constants.metadata.emptyRouteParams, existingErrorMessages, context.controllerObject);
}
}
});
return routeDescriptors[index];
}
}
}
// tslint:disable-next-line:no-null-keyword
throw new exceptions_1.NotFoundException();
}
/**
* Gets query string from request and saves query string in metatdata of controller object
* @param context HttpContext Object
* @param routeDescriptor RouteDescriptor object that holds metadata of api method
*/
function mapQueryString(context, routeDescriptor) {
if (context.request.query) {
const existingQueryStrings = Reflect.getMetadata(__1.Constants.metadata.queryString, context.controllerObject, routeDescriptor.methodName) || [];
Object.keys(context.request.query).forEach(qs => {
existingQueryStrings.push({
name: qs,
value: context.request.query[qs]
});
});
Reflect.defineMetadata(__1.Constants.metadata.queryString, existingQueryStrings, context.controllerObject, routeDescriptor.methodName);
}
}