UNPKG

node-web-mvc

Version:
205 lines (204 loc) 10.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); /** * @module RequestMappingHandlerMapping * @description controller请求方法映射处理器 */ const src_1 = __importDefault(require("../../hmr/src")); const AbstractHandlerMethodMapping_1 = __importDefault(require("./AbstractHandlerMethodMapping")); const RequestMappingInfo_1 = __importStar(require("./RequestMappingInfo")); const RequestMapping_1 = __importDefault(require("../annotations/mapping/RequestMapping")); const RuntimeAnnotation_1 = __importDefault(require("../annotations/annotation/RuntimeAnnotation")); const ElementType_1 = __importDefault(require("../annotations/annotation/ElementType")); const HttpStatusHandlerMethod_1 = __importDefault(require("../method/HttpStatusHandlerMethod")); const HttpStatus_1 = __importDefault(require("../http/HttpStatus")); const Tracer_1 = __importDefault(require("../annotations/annotation/Tracer")); const CorsOrigin_1 = __importDefault(require("../cors/CorsOrigin")); const CorsConfiguration_1 = __importDefault(require("../cors/CorsConfiguration")); const CorsUtils_1 = __importDefault(require("../util/CorsUtils")); const HttpHeaders_1 = __importDefault(require("../http/HttpHeaders")); const MediaType_1 = __importDefault(require("../http/MediaType")); const HandlerMapping_1 = require("./HandlerMapping"); const PathMatcher_1 = __importDefault(require("../util/PathMatcher")); class RequestMappingHandlerMapping extends AbstractHandlerMethodMapping_1.default { constructor() { super(); registerHotUpdate(this); } afterPropertiesSet() { this.registerAllAnnotationMappings(); } registerAnnotationMappings(annotation) { var _a; const isNotAction = annotation.elementType !== ElementType_1.default.METHOD; // 仅注册action路由 action路由 = controller路由 + action路由 if (isNotAction) return; const target = annotation.ctor; const name = `@${target.name}/${annotation.name}`; const anno = annotation.nativeAnnotation; const controllerAnno = (_a = RuntimeAnnotation_1.default.getClassAnnotation(target, RequestMapping_1.default)) === null || _a === void 0 ? void 0 : _a.nativeAnnotation; const produces = anno.produces || (controllerAnno === null || controllerAnno === void 0 ? void 0 : controllerAnno.produces) || ''; const requestMapping = new RequestMappingInfo_1.default(anno.value, anno.method, (0, RequestMappingInfo_1.ensureArray)(produces), anno.params, anno.headers, anno.consumes); const actionPaths = requestMapping.value || []; const controllerPaths = (0, RequestMappingInfo_1.ensureArray)((controllerAnno === null || controllerAnno === void 0 ? void 0 : controllerAnno.value) || ['']); const values = []; if (controllerPaths.length > 0) { // 合并controller路由 controllerPaths.forEach((controllerPath) => { actionPaths.map((actionPath) => { const exp = (controllerPath + '/' + actionPath).replace(/\/{2,3}/, '/'); values.push(exp); }); // 预构建模式缓存 PathMatcher_1.default.preBuildPattern(values); }); requestMapping.value = values; } // 覆盖为标准的produces anno.mapping = requestMapping; // 注册mapping this.registerHandlerMethod(name, requestMapping, target, annotation.method); } registerAllAnnotationMappings() { const annotations = RuntimeAnnotation_1.default.getAnnotations(RequestMapping_1.default); annotations.forEach((annotation) => { this.registerAnnotationMappings(annotation); }); } isConsumeable(servletContext, mapping) { const request = servletContext.request; const consumes = mapping.consumes || []; const contentType = request.headers['content-type']; if (consumes.length < 1) { return true; } return !!consumes.find((m) => contentType.indexOf(m) > -1); } checkRequest(servletContext, mapping, handler, requestMethod) { if (!mapping.method[requestMethod]) { return new HttpStatusHandlerMethod_1.default(HttpStatus_1.default.METHOD_NOT_ALLOWED); } else if (!this.isConsumeable(servletContext, mapping)) { return new HttpStatusHandlerMethod_1.default(HttpStatus_1.default.UNSUPPORTED_MEDIA_TYPE); } return handler; } getRequestMethod(request) { var _a; if (CorsUtils_1.default.isPreFlightRequest(request)) { return String((_a = request.getHeaderValue(HttpHeaders_1.default.ACCESS_CONTROL_REQUEST_METHOD)) === null || _a === void 0 ? void 0 : _a[0]).toUpperCase(); } else { return request.method; } } handleMatch(mapping, request) { const produces = mapping.produces || []; const mediaTypes = produces.map((m) => new MediaType_1.default(m)); request.setAttribute(HandlerMapping_1.PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE, mediaTypes); } match(registraction, path, request) { const mapping = registraction.getMapping(); const handlerMethod = registraction.getHandlerMethod(); const pathPatterns = mapping.value; const matcher = this.pathMatcher; const requestMethod = this.getRequestMethod(request); for (const pattern of pathPatterns) { const result = matcher.matchPattern(pattern, path); // 如果当前路由匹配成功 if (result && mapping.method[requestMethod]) { // 将匹配的路径变量值,设置到pathVariables request.pathVariables = result.params; const handler = this.checkRequest(request.servletContext, mapping, handlerMethod, requestMethod); this.handleMatch(mapping, request); return handler; } } } initCorsConfiguration(beanType, method) { var _a, _b, _c; const clazzCors = (_a = RuntimeAnnotation_1.default.getClassAnnotation(beanType, CorsOrigin_1.default)) === null || _a === void 0 ? void 0 : _a.nativeAnnotation; const methodCors = (_b = RuntimeAnnotation_1.default.getMethodAnnotation(beanType, method, CorsOrigin_1.default)) === null || _b === void 0 ? void 0 : _b.nativeAnnotation; if (clazzCors || methodCors) { const mapping = (_c = RuntimeAnnotation_1.default.getMethodAnnotation(beanType, method, RequestMapping_1.default)) === null || _c === void 0 ? void 0 : _c.nativeAnnotation; const corsConfig = new CorsConfiguration_1.default(); this.updateCorsConfig(corsConfig, clazzCors); this.updateCorsConfig(corsConfig, methodCors); const methods = mapping.method instanceof Array ? mapping.method : [mapping.method]; methods.forEach((method) => { corsConfig.addAllowedMethod(method); }); return corsConfig.applyPermitDefaultValues(); } } updateCorsConfig(config, anno) { var _a, _b, _c, _d, _e, _f, _g, _h; if (!anno) return; (_b = (_a = anno.origins) === null || _a === void 0 ? void 0 : _a.forEach) === null || _b === void 0 ? void 0 : _b.call(_a, (origin) => config.addAllowedOrigin(origin)); (_d = (_c = anno.originPatterns) === null || _c === void 0 ? void 0 : _c.forEach) === null || _d === void 0 ? void 0 : _d.call(_c, (pattern) => config.addAllowedOriginPattern(pattern)); (_f = (_e = anno.allowedHeaders) === null || _e === void 0 ? void 0 : _e.forEach) === null || _f === void 0 ? void 0 : _f.call(_e, (header) => config.addAllowedHeader(header)); (_h = (_g = anno.methods) === null || _g === void 0 ? void 0 : _g.forEach) === null || _h === void 0 ? void 0 : _h.call(_g, (method) => config.addAllowedMethod(method)); config.allowCredentials = anno.allowCredentials; config.allowPrivateNetwork = anno.allowPrivateNetwork; if (anno.maxAge >= 0) { config.maxAge = anno.maxAge; } } } exports.default = RequestMappingHandlerMapping; // 热更新支持 function registerHotUpdate(handlerMapping) { src_1.default .create(module) .clean() .preload((old) => { var _a; const file = old.filename; const registration = handlerMapping.getRegistrations(); const removeKeys = []; for (const element of registration.values()) { const beanType = (_a = element.getHandlerMethod()) === null || _a === void 0 ? void 0 : _a.beanType; if (Tracer_1.default.isDependency(beanType, file)) { removeKeys.push(element.getMapping()); } } removeKeys.forEach((item) => registration.delete(item)); }) .postend((latest) => { const file = latest.filename; const annotations = RuntimeAnnotation_1.default.getAnnotations(RequestMapping_1.default); annotations.forEach((annotation) => { if (Tracer_1.default.isDependency(annotation.ctor, file)) { handlerMapping.registerAnnotationMappings(annotation); } }); }); }