node-web-mvc
Version:
node spring mvc
205 lines (204 loc) • 10.5 kB
JavaScript
;
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);
}
});
});
}