跳转内容

Web

这节内容将介绍unioc后端部分。虽然叫做@unioc/web,但是它目前主要还是提供对Node/Bun/Deno等后端环境的适配与支持。它的主要职责是为多种不同的Web请求相关的框架和协议提供适配器,如RestfulWebSocket等。

Restful

@unioc/web内部提供了一个类扫描器(RestfulScanner),它实现了IRestfulScanner接口,并且关联了四个子类,下面将一一介绍。

IRestfulScanner

扫描器,提供一些方法来遍历和管理扫描到的类,还提供了另外一些便捷方法如mergePath(用来合并@RestController和方法注解上的@Get@Post等装饰器的路径)等。

类型定义

ts
export interface IRestfulScanner {
  /**
   * ### Merge the controller path and method path.
   *
   * 🔍 Merge the controller path and method path.
   *
   * @param controllerPath - The controller path.
   * @param methodPath - The method path.
   */
  
mergePath
(
controllerPath
: string,
methodPath
: string): string
/** * ### Add a new controller wrapper. * * 📉 Add a new controller wrapper. */
add
(
controller
: IRestControllerWrapper): this
/** * ### Find all the controller wrappers. * * 🚰 Find all the controller wrappers. * * @param force - Whether to force the search. */
findAll
(
force
?: boolean): IRestControllerWrapper[]
/** * ### Find all the method operators. * * 🚰 Find all the method operators. */
findAllMethodOperator
(): IRestMethodOperator[]
/** * ### Resolve all the controller wrappers. * * 👌 Resolve all the controller wrappers. */
resolveAll
():
Promise
<this>
/** * ### Search for the method operator by full path. * * 🔍 Search for the method operator by full path. * * @param fullPath - The full path. Must start with `/`. */
search
(
fullPath
: `/${string}`): IRestMethodOperator[]
/** * ### Resolve the node handler. * * 🐢 Resolve the node handler for the current scanner. */
resolveNodeHandler
?():
Awaitable
<IRestfulNode.
Handler
>
/** * ### Resolve the connect handler. * * 🔗 Resolve the connect handler for the current scanner. */
resolveConnectHandler
?():
Awaitable
<IRestfulConnect.
Handler
>
/** * ### Resolve the context handler. * * ⛰️ Resolve the context handler for the current scanner. */
resolveContextHandler
?():
Awaitable
<IRestfulContext.
Handler
>
/** * ### Resolve the web standard handler. * * 🌐 Resolve the web standard handler for the current scanner. */
resolveWebStandardHandler
?():
Awaitable
<IRestfulWebStandard.
Handler
>
}

IRestControllerWrapper

控制器wrapper,每个wrapper有一个对应一个核心包的IClassWrapper用来导航到IoC容器,在这层还可以获取到整体的@RestController级别的装饰器元数据。比如有如下伪代码:

ts
@RestController('/api')
@RestController('/api2')
class RestController {}

那么定义的两个前缀路由都可以通过getFullControllerOptions等方法,由这层完整读取。

类型定义

ts
export interface IRestControllerWrapper {
  /**
   * ### Get the restful scanner.
   *
   * 🔍 Get the restful scanner.
   */
  
getRestfulScanner
(): IRestfulScanner
/** * ### Get the class wrapper. * * 🔍 Get the class wrapper. */
getClassWrapper
():
IClassWrapper
/** * ### Get the current controller options. * * ⚙️ Get the current controller options. */
getFullControllerOptions
(): RestController.
Options
[]
/** * ### Get the current method options. * * ⚙️ Get the current method options. */
getFullMethodOptions
(): IHttpMethodMetadata[]
/** * ### Find all the controller operators. * * 🚰 Find all the controller operators. * * @param force - Whether to force the search. */
findAll
(
force
?: boolean): IRestControllerOperator[]
/** * ### Add a new controller operator. * * 📉 Add a new controller operator. */
add
(
operator
: IRestControllerOperator): this
}

IRestControllerOperator

这一层为遍历了IRestControllerWrapper后获取到的单个@RestController信息,比如上面的例子:

ts
@RestController('/api')
@RestController('/api2')
class AppController {}

那么这一层将一一读取/api/api2两个路径,并提供便捷方法获取到它们。

类型定义

ts
export interface IRestControllerOperator {
  /**
   * ### Get the current controller wrapper.
   *
   * 🔍 Get the current controller wrapper.
   */
  
getControllerWrapper
(): IRestControllerWrapper
/** * ### Get the current controller path. * * 📃 Get the current controller path. */
getControllerPath
(): string
/** * ### Get the current controller options. * * ⚙️ Get the current controller options. */
getFullControllerOptions
(): RestController.
Options
/** * ### Find all the method wrappers. * * 🚰 Find all the method wrappers. * * @param force - Whether to force the search. */
findAll
(
force
?: boolean): IRestMethodWrapper[]
/** * ### Add a new method wrapper. * * 📉 Add a new method wrapper. */
add
(
operator
: IRestMethodWrapper): this
}

IRestMethodWrapper

方法wrapper,可以获取到当前方法的propertyKey等,并且提供一些便捷方法获取当前方法的反射信息,如getReturnTypegetParamTypes等。此外,还提供execute方法来执行当前方法。

类型定义

ts
export interface IRestMethodWrapper {
  /**
   * ### Get the current controller operator.
   *
   * 🔍 Get the current controller operator.
   */
  
getControllerOperator
(): IRestControllerOperator
/** * ### Get the current property key. * * 🌾 Get the current property key. */
getPropertyKey
():
PropertyKey
/** * ### Execute the current method. * * 📖 Execute the current method. */
execute
<
T
,
TE
>(
args
: unknown[],
extraOptions
:
Record
<string, unknown>):
Promise
<
IResult
<
T
,
TE
>>
/** * ### Get the current method's return type. * * 😚 Shortcut to get the current method's return type by IMetadataScanner. */
getReturnType
():
IClass
| undefined
/** * ### Get the current method's param types. * * 😚 Shortcut to get the current method's param types by IMetadataScanner. */
getParamTypes
():
IClass
[]
/** * ### Find all the method operators. * * 🚰 Find all the method operators. * * @param force - Whether to force the search. */
findAll
(
force
?: boolean): IRestMethodOperator[]
/** * ### Add a new method operator. * * 📉 Add a new method operator. */
add
(
operator
: IRestMethodOperator): this
}

IRestMethodOperator

方法操作符,获取当前方法的单个路由信息,可以获取到当前方法中,当前注解所设置的httpMethodpath等,并且提供一些便捷方法如getFullPath(帮你自动调用IRestfulScanner.mergePath合并@RestController和方法注解上的路径)等。

类型定义

ts
export interface IRestMethodOperator {
  /**
   * ### Get the current method wrapper.
   *
   * 🔍 Get the current method wrapper.
   */
  
getMethodWrapper
(): IRestMethodWrapper
/** * ### Get the current http method. * * 🌍 Get the current http method.Get the current http method. */
getHttpMethod
():
IHttpMethod
/** * ### Get the current full path. * * 🧮 Computed to full path using `mergePath`. * It will merge the {@linkcode IRestControllerOperator.getControllerPath} and {@linkcode getPath}. */
getFullPath
(): string
/** * ### Get the current path. * * 📃 Get the current method path. */
getPath
(): string
/** * ### Get the current method options. * * ⚙️ Get the full current method's options. */
getFullMethodOptions
(): IHttpMethodMetadata
}

为什么我们需要这么复杂的设计?

上面的设计虽然繁杂,但是能使得任何其他的框架都可以通过@unioc/web的适配器来实现对uniocRestful功能的支持。

为了尽量保持简单明了我们已经尽了最大的努力,使得甚至几乎每一个人都能快速制作成一些装饰器甚至是实现自己的Web适配器框架,或者当一些性能更好的Web框架出现时,可以快速实现适配,可用性、可扩展性拉满 🚀

对于IoC框架层

可以通过继承这些基实现类,来实现任意Web IoC框架的适配,如@unioc/adapter-nestjs

ts
import type { IRestfulScanner } from 'unioc/web'
import { RestfulScanner } from 'unioc/web'

export class NestJsRestfulScanner extends RestfulScanner implements IRestfulScanner {
  // 重写需要重写的方法即可
}

对于Web框架层

通过统一的接口来对整个容器中的所有控制器以及方法进行快捷遍历,如@unioc/web-express,代码仅仅只有一点点,就做到了对express框架的适配,因为大部分工作都由@unioc/web来完成了。

贡献者

页面历史