feat: complate @ccms/web package
Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
		@@ -1,2 +1,16 @@
 | 
			
		||||
export const WebProxyBeanName = 'webServerProxy'
 | 
			
		||||
export const FilterProxyBeanName = 'webFilterProxy'
 | 
			
		||||
export const METADATA_KEY = {
 | 
			
		||||
    Controller: Symbol("@ccms/web:Controller"),
 | 
			
		||||
    Action: Symbol("@ccms/web:Action"),
 | 
			
		||||
    Param: Symbol("@ccms/web:Param"),
 | 
			
		||||
    Middleware: Symbol("@ccms/web:Middleware"),
 | 
			
		||||
}
 | 
			
		||||
export enum PARAM_TYPE {
 | 
			
		||||
    QUERY = 'QUERY',
 | 
			
		||||
    BODY = 'BODY',
 | 
			
		||||
    HEADER = 'HEADER',
 | 
			
		||||
    COOKIE = 'COOKIE',
 | 
			
		||||
    REQUEST = 'REQUEST',
 | 
			
		||||
    RESPONSE = 'RESPONSE',
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,30 +1,80 @@
 | 
			
		||||
export const Controller = () => {
 | 
			
		||||
    return <TFunction extends Function>(target: TFunction): ClassDecorator => {
 | 
			
		||||
import { decorate, injectable } from "@ccms/container"
 | 
			
		||||
 | 
			
		||||
import { METADATA_KEY, PARAM_TYPE } from '../constants'
 | 
			
		||||
import { interfaces } from "../interfaces"
 | 
			
		||||
import { addControllerMetadata, addControllerAction, addActionParam } from "./utils"
 | 
			
		||||
 | 
			
		||||
export const Controller = (metadata?: string | interfaces.ControllerMetadata) => {
 | 
			
		||||
    return (target: any) => {
 | 
			
		||||
        if (!metadata) { metadata = target.name.toLowerCase().replace('controller', '') }
 | 
			
		||||
        if (typeof metadata === "string") { metadata = { path: metadata } }
 | 
			
		||||
        metadata.name = metadata.name || target.name
 | 
			
		||||
        metadata.path = metadata.path ?? `/${metadata}`
 | 
			
		||||
        metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}`
 | 
			
		||||
        decorate(injectable(), target)
 | 
			
		||||
        Reflect.defineMetadata(METADATA_KEY.Controller, metadata, target)
 | 
			
		||||
        addControllerMetadata(metadata)
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const Post = () => {
 | 
			
		||||
    return <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>): MethodDecorator => {
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
function action(method: interfaces.Method) {
 | 
			
		||||
    return (metadata?: string | interfaces.ActionMetadata) => {
 | 
			
		||||
        return (target: any, propertyKey: string) => {
 | 
			
		||||
            if (!metadata) { metadata = propertyKey.toLowerCase() }
 | 
			
		||||
            if (typeof metadata === "string") { metadata = { path: metadata } }
 | 
			
		||||
            metadata.path = metadata.path ?? `/${propertyKey}`
 | 
			
		||||
            metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}`
 | 
			
		||||
            metadata.method = method
 | 
			
		||||
            metadata.executor = propertyKey
 | 
			
		||||
            Reflect.defineMetadata(METADATA_KEY.Action, metadata, target[propertyKey])
 | 
			
		||||
            addControllerAction(target, propertyKey)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const Get = () => {
 | 
			
		||||
    return <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>): MethodDecorator => {
 | 
			
		||||
        return
 | 
			
		||||
export const Action = action('ALL')
 | 
			
		||||
export const Get = action('GET')
 | 
			
		||||
export const Post = action('POST')
 | 
			
		||||
export const Put = action('PUT')
 | 
			
		||||
export const Patch = action('PATCH')
 | 
			
		||||
export const Head = action('HEAD')
 | 
			
		||||
export const Delete = action('DELETE')
 | 
			
		||||
 | 
			
		||||
function param(type: PARAM_TYPE) {
 | 
			
		||||
    return (metadata?: string | interfaces.ParamMetadata) => {
 | 
			
		||||
        return (target: any, propertyKey: string, index: number) => {
 | 
			
		||||
            if (!metadata) { metadata = `${propertyKey}-${index}` }
 | 
			
		||||
            if (typeof metadata === "string") { metadata = { name: metadata } }
 | 
			
		||||
            metadata.type = type
 | 
			
		||||
            metadata.index = index
 | 
			
		||||
            metadata.paramtype = Reflect.getMetadata("design:paramtypes", target, propertyKey)[index]
 | 
			
		||||
            addActionParam(target, propertyKey, metadata)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const Header = () => {
 | 
			
		||||
    return <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>): MethodDecorator => {
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const Param = () => {
 | 
			
		||||
    return (target: Object, propertyKey: string | symbol, parameterIndex: number): ParameterDecorator => {
 | 
			
		||||
        return
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
export const RequestBody = () => {
 | 
			
		||||
    return (target: Object, propertyKey: string | symbol, parameterIndex: number): ParameterDecorator => {
 | 
			
		||||
        return
 | 
			
		||||
export const Request = param(PARAM_TYPE.REQUEST)
 | 
			
		||||
export const Response = param(PARAM_TYPE.RESPONSE)
 | 
			
		||||
export const Header = param(PARAM_TYPE.HEADER)
 | 
			
		||||
export const Cookie = param(PARAM_TYPE.COOKIE)
 | 
			
		||||
export const Query = param(PARAM_TYPE.QUERY)
 | 
			
		||||
export const Param = param(PARAM_TYPE.QUERY)
 | 
			
		||||
export const Body = param(PARAM_TYPE.BODY)
 | 
			
		||||
 | 
			
		||||
function Middleware() {
 | 
			
		||||
    return (metadata?: string | interfaces.ActionMetadata) => {
 | 
			
		||||
        return (target: any, propertyKey: string) => {
 | 
			
		||||
            if (!metadata) { metadata = propertyKey.toLowerCase() }
 | 
			
		||||
            if (typeof metadata === "string") { metadata = { path: metadata } }
 | 
			
		||||
            metadata.path = metadata.path ?? `/${propertyKey}`
 | 
			
		||||
            metadata.path = metadata.path.startsWith('/') ? metadata.path : `/${metadata.path}`
 | 
			
		||||
            metadata.executor = propertyKey
 | 
			
		||||
            Reflect.defineMetadata(METADATA_KEY.Action, metadata, target[propertyKey])
 | 
			
		||||
            addControllerAction(target, propertyKey)
 | 
			
		||||
            return
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export * from './utils'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								packages/web/src/decorators/utils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								packages/web/src/decorators/utils.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
import { interfaces } from '../interfaces'
 | 
			
		||||
import { METADATA_KEY } from '../constants'
 | 
			
		||||
 | 
			
		||||
export function getControllerMetadatas(): interfaces.ControllerMetadata[] {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Controller, Reflect) || []
 | 
			
		||||
}
 | 
			
		||||
export function addControllerMetadata(metadata: interfaces.ControllerMetadata) {
 | 
			
		||||
    Reflect.defineMetadata(METADATA_KEY.Controller, [metadata, ...getControllerMetadatas()], Reflect)
 | 
			
		||||
}
 | 
			
		||||
export function getControllerActions(target: any): string[] {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Action, target.constructor) || []
 | 
			
		||||
}
 | 
			
		||||
export function addControllerAction(target: any, propertyKey: string) {
 | 
			
		||||
    Reflect.defineMetadata(METADATA_KEY.Action, [propertyKey, ...getControllerActions(target)], target.constructor)
 | 
			
		||||
}
 | 
			
		||||
export function getControllerMetadata(target: any): interfaces.ControllerMetadata {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Controller, target)
 | 
			
		||||
}
 | 
			
		||||
export function getActionMetadata(target: any, propertyKey: string): interfaces.ActionMetadata {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Action, target[propertyKey])
 | 
			
		||||
}
 | 
			
		||||
export function getActionParams(target: any, propertyKey: string): interfaces.ParamMetadata[] {
 | 
			
		||||
    return Reflect.getMetadata(METADATA_KEY.Param, target[propertyKey]) || []
 | 
			
		||||
}
 | 
			
		||||
export function addActionParam(target: any, propertyKey: string, metadata: interfaces.ParamMetadata) {
 | 
			
		||||
    Reflect.defineMetadata(METADATA_KEY.Param, [metadata, ...getActionParams(target, propertyKey)], target[propertyKey])
 | 
			
		||||
}
 | 
			
		||||
@@ -6,5 +6,6 @@
 | 
			
		||||
/// <reference types="@javatypes/spring-beans" />
 | 
			
		||||
 | 
			
		||||
export * from './server'
 | 
			
		||||
export * from './constants'
 | 
			
		||||
export * from './decorators'
 | 
			
		||||
export * from './interfaces'
 | 
			
		||||
 
 | 
			
		||||
@@ -5,14 +5,20 @@ export interface InterceptorAdapter {
 | 
			
		||||
    postHandle?(ctx: Context): void
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type RequestHeader = { [key: string]: string | string[] }
 | 
			
		||||
export type RequestParams = { [key: string]: string | string[] }
 | 
			
		||||
type StringKeyAndStringValue = { [key: string]: string }
 | 
			
		||||
type StringKeyAndStringOrArrayValue = { [key: string]: string | string[] }
 | 
			
		||||
 | 
			
		||||
export type RequestHeaders = StringKeyAndStringOrArrayValue
 | 
			
		||||
export type RequestParams = StringKeyAndStringOrArrayValue
 | 
			
		||||
export type RequestCookies = StringKeyAndStringValue
 | 
			
		||||
 | 
			
		||||
export interface Context {
 | 
			
		||||
    request?: javax.servlet.http.HttpServletRequest
 | 
			
		||||
    response?: javax.servlet.http.HttpServletResponse
 | 
			
		||||
    header?: RequestHeader
 | 
			
		||||
    handler?: RequestHandler
 | 
			
		||||
    url?: string
 | 
			
		||||
    headers?: RequestHeaders
 | 
			
		||||
    cookies?: RequestCookies
 | 
			
		||||
    params?: RequestParams
 | 
			
		||||
    body?: any
 | 
			
		||||
    result?: any
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,77 @@
 | 
			
		||||
export interface BaseMetadata {
 | 
			
		||||
    /**
 | 
			
		||||
     * 名称 为空则为对象名称
 | 
			
		||||
     */
 | 
			
		||||
    name?: string
 | 
			
		||||
    /**
 | 
			
		||||
     * 支持的服务器列表 为空则代表所有
 | 
			
		||||
     */
 | 
			
		||||
    servers?: string[]
 | 
			
		||||
}
 | 
			
		||||
import { PARAM_TYPE } from "../constants"
 | 
			
		||||
 | 
			
		||||
export interface ControllerMetadata extends BaseMetadata {
 | 
			
		||||
export namespace interfaces {
 | 
			
		||||
    export interface BaseMetadata {
 | 
			
		||||
        /**
 | 
			
		||||
         * 名称 为空则为对象名称
 | 
			
		||||
         */
 | 
			
		||||
        name?: string
 | 
			
		||||
        /**
 | 
			
		||||
         * 支持的服务器列表 为空则代表所有
 | 
			
		||||
         */
 | 
			
		||||
        servers?: string[]
 | 
			
		||||
    }
 | 
			
		||||
    export interface WebMetadata extends BaseMetadata {
 | 
			
		||||
        /**
 | 
			
		||||
         * 路径
 | 
			
		||||
         */
 | 
			
		||||
        path: string
 | 
			
		||||
        /**
 | 
			
		||||
         * 对象
 | 
			
		||||
         */
 | 
			
		||||
        target?: string
 | 
			
		||||
    }
 | 
			
		||||
    export interface ControllerMetadata extends WebMetadata {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    interface Newable<T> {
 | 
			
		||||
        new(...args: any[]): T
 | 
			
		||||
    }
 | 
			
		||||
    interface Abstract<T> {
 | 
			
		||||
        prototype: T
 | 
			
		||||
    }
 | 
			
		||||
    export type ServiceIdentifier<T> = (string | symbol | Newable<T> | Abstract<T>)
 | 
			
		||||
    export interface MiddlewareMetadata extends BaseMetadata {
 | 
			
		||||
        /**
 | 
			
		||||
         * 中间件名称列表
 | 
			
		||||
         */
 | 
			
		||||
        names: Array<ServiceIdentifier<any>>
 | 
			
		||||
    }
 | 
			
		||||
    export type Method = 'ALL' | 'GET' | 'HEAD' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'TRACE'
 | 
			
		||||
    export interface ActionMetadata extends WebMetadata {
 | 
			
		||||
        /**
 | 
			
		||||
         * 请求方法
 | 
			
		||||
         */
 | 
			
		||||
        method?: Method
 | 
			
		||||
        /**
 | 
			
		||||
         * 执行器
 | 
			
		||||
         */
 | 
			
		||||
        executor?: string
 | 
			
		||||
    }
 | 
			
		||||
    export interface ParamMetadata extends BaseMetadata {
 | 
			
		||||
        /**
 | 
			
		||||
         * 参数类型
 | 
			
		||||
         */
 | 
			
		||||
        type?: PARAM_TYPE
 | 
			
		||||
        /**
 | 
			
		||||
         * 默认值
 | 
			
		||||
         */
 | 
			
		||||
        default?: any
 | 
			
		||||
        /**
 | 
			
		||||
         * 参数位置
 | 
			
		||||
         */
 | 
			
		||||
        index?: number
 | 
			
		||||
        /**
 | 
			
		||||
         * 参数对象类型
 | 
			
		||||
         */
 | 
			
		||||
        paramtype?: NewableFunction
 | 
			
		||||
        /**
 | 
			
		||||
         * 是否必传
 | 
			
		||||
         */
 | 
			
		||||
        require?: boolean
 | 
			
		||||
        /**
 | 
			
		||||
         * 异常消息
 | 
			
		||||
         */
 | 
			
		||||
        message?: string
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,16 @@
 | 
			
		||||
import * as querystring from 'querystring'
 | 
			
		||||
 | 
			
		||||
import { web } from '@ccms/api'
 | 
			
		||||
import { provideSingleton, JSClass, postConstruct } from '@ccms/container'
 | 
			
		||||
import { provideSingleton, JSClass, postConstruct, Container, ContainerInstance, inject } from '@ccms/container'
 | 
			
		||||
 | 
			
		||||
import { WebProxyBeanName, FilterProxyBeanName } from './constants'
 | 
			
		||||
import { Context, InterceptorAdapter, RequestHandler } from './interfaces'
 | 
			
		||||
import { WebProxyBeanName, FilterProxyBeanName, METADATA_KEY, PARAM_TYPE } from './constants'
 | 
			
		||||
import { Context, InterceptorAdapter, RequestHandler, interfaces } from './interfaces'
 | 
			
		||||
import { getControllerActions, getActionMetadata, getControllerMetadata, getActionParams } from './decorators'
 | 
			
		||||
 | 
			
		||||
const HttpServletRequestWrapper = Java.type('javax.servlet.http.HttpServletRequestWrapper')
 | 
			
		||||
const HttpServletResponseWrapper = Java.type('javax.servlet.http.HttpServletResponseWrapper')
 | 
			
		||||
const ServletInputStream = Java.type('javax.servlet.ServletInputStream')
 | 
			
		||||
const ServletOutputStream = Java.type('javax.servlet.ServletOutputStream')
 | 
			
		||||
 | 
			
		||||
@provideSingleton(web.Server)
 | 
			
		||||
export class Server {
 | 
			
		||||
@@ -13,11 +19,14 @@ export class Server {
 | 
			
		||||
    @JSClass('pw.yumc.MiaoScript.web.WebFilterProxy')
 | 
			
		||||
    private WebFilterProxy: any
 | 
			
		||||
 | 
			
		||||
    @inject(ContainerInstance)
 | 
			
		||||
    private container: Container
 | 
			
		||||
 | 
			
		||||
    private StreamUtils = org.springframework.util.StreamUtils
 | 
			
		||||
    private ResponseEntity = org.springframework.http.ResponseEntity
 | 
			
		||||
 | 
			
		||||
    private interceptors: Map<string, InterceptorAdapter>
 | 
			
		||||
    private handlerMapping: Map<string, RequestHandler>
 | 
			
		||||
    private methodMappings: Map<string, Map<string, RequestHandler>>
 | 
			
		||||
 | 
			
		||||
    private beanFactory: org.springframework.beans.factory.support.DefaultListableBeanFactory
 | 
			
		||||
 | 
			
		||||
@@ -25,7 +34,7 @@ export class Server {
 | 
			
		||||
    initialization() {
 | 
			
		||||
        this.beanFactory = base.getInstance().getAutowireCapableBeanFactory()
 | 
			
		||||
        this.interceptors = new Map()
 | 
			
		||||
        this.handlerMapping = new Map()
 | 
			
		||||
        this.methodMappings = new Map()
 | 
			
		||||
        this.start()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -43,13 +52,77 @@ export class Server {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registryController(target: any) {
 | 
			
		||||
        if (!target) { throw new Error('Controller can\'t be undefiend!') }
 | 
			
		||||
        let controllerMetadata = getControllerMetadata(target)
 | 
			
		||||
        if (!controllerMetadata) { throw new Error(`Controller ${target.name} must have @Controller decorator!`) }
 | 
			
		||||
        try {
 | 
			
		||||
            this.container.rebind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name)
 | 
			
		||||
        } catch{
 | 
			
		||||
            this.container.bind(METADATA_KEY.Controller).to(target).inSingletonScope().whenTargetNamed(target.name)
 | 
			
		||||
        }
 | 
			
		||||
        target = this.container.getNamed(METADATA_KEY.Controller, target.name)
 | 
			
		||||
        let actions = getControllerActions(target)
 | 
			
		||||
        for (const action of actions) {
 | 
			
		||||
            let actionMetadata = getActionMetadata(target, action)
 | 
			
		||||
            let path = `${controllerMetadata.path || ''}${actionMetadata.path || ''}`
 | 
			
		||||
            if (!path) throw new Error(`Controller ${controllerMetadata.name} Action ${actionMetadata.name} path is empty!`)
 | 
			
		||||
            if (!this.methodMappings.has(path)) { this.methodMappings.set(path, new Map()) }
 | 
			
		||||
            console.debug(`Controller ${controllerMetadata.name} Registry ${path} to ${actionMetadata.executor || '<anonymous>'} Action function.`)
 | 
			
		||||
            this.methodMappings.get(path).set(actionMetadata.method || 'ALL', (ctx: Context) => {
 | 
			
		||||
                let args = []
 | 
			
		||||
                let params = getActionParams(target, action)
 | 
			
		||||
                for (const index in params) {
 | 
			
		||||
                    let param = params[index]
 | 
			
		||||
                    let paramValue = undefined
 | 
			
		||||
                    switch (param.type) {
 | 
			
		||||
                        case PARAM_TYPE.REQUEST: paramValue = ctx.request; break
 | 
			
		||||
                        case PARAM_TYPE.RESPONSE: paramValue = ctx.response; break
 | 
			
		||||
                        case PARAM_TYPE.QUERY: paramValue = ctx.params[param.name]; break
 | 
			
		||||
                        case PARAM_TYPE.HEADER: paramValue = ctx.headers[param.name]; break
 | 
			
		||||
                        case PARAM_TYPE.BODY: paramValue = ctx.body; break
 | 
			
		||||
                        case PARAM_TYPE.COOKIE: paramValue = ctx.cookies[param.name]; break
 | 
			
		||||
                    }
 | 
			
		||||
                    if (param.require && !paramValue) {
 | 
			
		||||
                        return {
 | 
			
		||||
                            status: 400,
 | 
			
		||||
                            msg: param.message ?? `Param Type ${param.type} require not empty!`,
 | 
			
		||||
                            data: param
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    args[param.index] = paramValue ?? param.default
 | 
			
		||||
                }
 | 
			
		||||
                return target[actionMetadata.executor].apply(target, args)
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unregistryController(target: any) {
 | 
			
		||||
        if (!target) { throw new Error('Controller can\'t be undefiend!') }
 | 
			
		||||
        let controllerMetadata = getControllerMetadata(target)
 | 
			
		||||
        if (!controllerMetadata) { throw new Error(`Controller ${target.name} must have @Controller decorator!`) }
 | 
			
		||||
        try {
 | 
			
		||||
            target = this.container.getNamed(METADATA_KEY.Controller, target.name)
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            throw new Error(`Controller ${target.name} not registry! err: ${error}`)
 | 
			
		||||
        }
 | 
			
		||||
        let actions = getControllerActions(target)
 | 
			
		||||
        for (const action of actions) {
 | 
			
		||||
            let actionMetadata = getActionMetadata(target, action)
 | 
			
		||||
            let path = `${controllerMetadata.path || ''}${actionMetadata.path || ''}`
 | 
			
		||||
            if (!this.methodMappings.has(path)) { continue }
 | 
			
		||||
            this.methodMappings.get(path).delete(actionMetadata.method)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registryMapping(path: string, handler: RequestHandler) {
 | 
			
		||||
        console.debug(`Registry Mapping ${path} to handle ${handler.name || '<anonymous>'} function.`)
 | 
			
		||||
        this.handlerMapping.set(path, handler)
 | 
			
		||||
        if (!this.methodMappings.has(path)) { this.methodMappings.set(path, new Map()) }
 | 
			
		||||
        this.methodMappings.get(path).set("ALL", handler)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unregistryMapping(path: string) {
 | 
			
		||||
        this.handlerMapping.delete(path)
 | 
			
		||||
        if (this.methodMappings.has(path)) { this.methodMappings.get(path).delete("ALL") }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    registryInterceptor(interceptor: InterceptorAdapter) {
 | 
			
		||||
@@ -65,28 +138,72 @@ export class Server {
 | 
			
		||||
        try { this.beanFactory.destroySingleton(FilterProxyBeanName) } catch (ex) { }
 | 
			
		||||
        var WebFilterProxyNashorn = Java.extend(this.WebFilterProxy, {
 | 
			
		||||
            doFilter: (servletRequest: javax.servlet.http.HttpServletRequest, servletResponse: javax.servlet.http.HttpServletResponse, filterChain: javax.servlet.FilterChain) => {
 | 
			
		||||
                console.log('WebFilterProxyNashorn', 'doFilter', servletRequest, servletResponse)
 | 
			
		||||
                filterChain.doFilter(servletRequest, servletResponse)
 | 
			
		||||
            }
 | 
			
		||||
        })
 | 
			
		||||
        this.beanFactory.registerSingleton(FilterProxyBeanName, new WebFilterProxyNashorn())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // private getRequestWrapper(servletRequest: javax.servlet.http.HttpServletRequest) {
 | 
			
		||||
    //     var body = org.springframework.util.StreamUtils.copyToByteArray(servletRequest.getInputStream())
 | 
			
		||||
    //     var HttpServletRequestWrapperAdapter = Java.extend(HttpServletRequestWrapper, {
 | 
			
		||||
    //         getInputStream: () => {
 | 
			
		||||
    //             var bais = new java.io.ByteArrayInputStream(body)
 | 
			
		||||
    //             return new ServletInputStream({
 | 
			
		||||
    //                 read: () => bais.read(),
 | 
			
		||||
    //                 isFinished: () => bais.available() == 0
 | 
			
		||||
    //             })
 | 
			
		||||
    //         }
 | 
			
		||||
    //     })
 | 
			
		||||
    //     var wrapper = new HttpServletRequestWrapperAdapter(servletRequest)
 | 
			
		||||
    //     return wrapper
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    // private getResponseWrapper(servletResponse: javax.servlet.http.HttpServletResponse) {
 | 
			
		||||
    //     var HttpServletRequestWrapperAdapter = Java.extend(HttpServletRequestWrapper, {
 | 
			
		||||
    //         getOutputStream: () => {
 | 
			
		||||
    //             return new ServletOutputStream({
 | 
			
		||||
    //             })
 | 
			
		||||
    //         }
 | 
			
		||||
    //     })
 | 
			
		||||
    //     var wrapper = new HttpServletRequestWrapperAdapter(servletResponse)
 | 
			
		||||
    //     return wrapper
 | 
			
		||||
    // }
 | 
			
		||||
 | 
			
		||||
    private notFound(method: string, path: string) {
 | 
			
		||||
        return {
 | 
			
		||||
            status: 404,
 | 
			
		||||
            msg: "handlerMapping Not Found!",
 | 
			
		||||
            method,
 | 
			
		||||
            path,
 | 
			
		||||
            timestamp: Date.now()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private registryWebProxy() {
 | 
			
		||||
        try { this.beanFactory.destroySingleton(WebProxyBeanName) } catch (ex) { }
 | 
			
		||||
        var WebServerProxyNashorn = Java.extend(this.WebServerProxy, {
 | 
			
		||||
            process: (req: javax.servlet.http.HttpServletRequest, resp: javax.servlet.http.HttpServletResponse) => {
 | 
			
		||||
                let ctx: Context = { request: req, response: resp }
 | 
			
		||||
                let path = req.getRequestURI()
 | 
			
		||||
                if (!this.methodMappings.has(path)) return this.notFound(req.getMethod(), path)
 | 
			
		||||
                let mappings = this.methodMappings.get(req.getRequestURI())
 | 
			
		||||
                let handler = mappings.get(req.getMethod()) || mappings.get("ALL")
 | 
			
		||||
                if (!handler) return this.notFound(req.getMethod(), path)
 | 
			
		||||
                let ctx: Context = { request: req, response: resp, params: {}, body: {}, handler }
 | 
			
		||||
                ctx.url = req.getRequestURI()
 | 
			
		||||
                // @ts-ignore
 | 
			
		||||
                ctx.header = { __noSuchProperty__: (name: string) => req.getHeader(name) + '' }
 | 
			
		||||
                ctx.headers = { __noSuchProperty__: (name: string) => req.getHeader(name) }
 | 
			
		||||
                ctx.cookies = {}
 | 
			
		||||
                for (const cookie of (req.getCookies() || [])) {
 | 
			
		||||
                    ctx.cookies[cookie.getName()] = cookie.getValue()
 | 
			
		||||
                }
 | 
			
		||||
                if (req.getQueryString()) {
 | 
			
		||||
                    ctx.url += `?${req.getQueryString()}`
 | 
			
		||||
                    ctx.params = querystring.parse(req.getQueryString())
 | 
			
		||||
                }
 | 
			
		||||
                if (req.getMethod() == "POST") {
 | 
			
		||||
                    ctx.body = this.StreamUtils.copyToString(req.getInputStream(), java.nio.charset.StandardCharsets.UTF_8)
 | 
			
		||||
                    if ((ctx.header['Content-Type'] || '').includes('application/json')) {
 | 
			
		||||
                    if ((ctx.headers['Content-Type'] || '').includes('application/json')) {
 | 
			
		||||
                        try {
 | 
			
		||||
                            ctx.body = JSON.parse(ctx.body)
 | 
			
		||||
                        } catch (error) {
 | 
			
		||||
@@ -158,6 +275,7 @@ export class Server {
 | 
			
		||||
===================== MiaoSpring =====================
 | 
			
		||||
Request  Method : ${ctx.request.getMethod()}
 | 
			
		||||
Request  URL    : ${ctx.url}
 | 
			
		||||
Request  Body   : ${JSON.stringify(ctx.body)}
 | 
			
		||||
Response Body   : ${JSON.stringify(Java.asJSONCompatible(ctx.result))}
 | 
			
		||||
Handle   Time   : ${Date.now() - startTime}ms
 | 
			
		||||
======================================================`)
 | 
			
		||||
@@ -165,16 +283,8 @@ Handle   Time   : ${Date.now() - startTime}ms
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private execRequestHandle(ctx: Context) {
 | 
			
		||||
        if (!this.handlerMapping.has(ctx.request.getRequestURI())) {
 | 
			
		||||
            return {
 | 
			
		||||
                status: 404,
 | 
			
		||||
                msg: "handlerMapping Not Found!",
 | 
			
		||||
                path: ctx.url,
 | 
			
		||||
                timestamp: Date.now()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            return this.handlerMapping.get(ctx.request.getRequestURI())(ctx)
 | 
			
		||||
            return ctx.handler(ctx)
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            return {
 | 
			
		||||
                status: 500,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user