eggjs / eggjs/tegg

[RFC] 增强Controller能力与相关HttpMethod

Open
#22 14 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
264
Forks
46
Avg merge
2d 22h
Merged PRs (30d)
1

Description

- 开始时间: 2021/12/16
- RFC PR:
- tegg Issue:

## 背景

参照: [提供更加简单化请求方法的修饰器](https://github.com/eggjs/tegg/issues/18)的讨论

## 思路

### 所有Controller 类型会通过namespace进行区分

- 为了方便区分`Controller`,`RestController`,`HttpController`,`RpcControlle`需要单独划分命名空间以方便归类。 将HttpController和简化后的Controller将会被划分到
http namespace, RestController 会被划分到rest namespace,`RpcControlle`会被划分到 rpc namespace。

- 以下将通过`import`的形式具体描述:

```typescript
import {Controller, HttpController} from '@eggjs/tegg/http';
import {RestController} from '@eggjs/tegg/rest';
import {RpcController} from '@eggjs/tegg/rpc';
```

### 新增baseRoot

- config新增baseRoot能力

```typescript
tegg:{
baseRoot:string
}
```

- 通过这个字段可以全局调整路由根路径

```typescript
//config.default.ts
tegg:{
baseRoot:'/tegg'
}

//controller/fruitController.ts

@RestController('/api/v1')
//or Controller('/api/v1')
class Fruit {
// GET /api/v1/
@List
home() {
}
}
```

此时路径会被修正到‘/tegg/api/v1'’

### 新增Controller

- 所有的方法入参暂定为继承自HttpController:

```typescript
Controller(path?: string, protoName?: string, controllerName?: string);
```

### 新增Controller下Http Method修饰器

- 新的`Http Method` 会跟 `HTTPMethodEnum` 的枚举保持一致,包含 `GET`,`POST`,`PUT`,`DELETE`,`PATCH`,`OPTIONS`,`HEAD`
- 所有的方法入参暂时定为继承自HTTPMethod,以GET为例:
```typescript
Get(path?: string, priority?: number)
```
- 与HTTPMethod不同的是Get第一个入参为可选,如果Get的`path`入参为空时, 可以通过检索Handler Function 名称自动匹配路径。 下面以GET为例:
```typescript
@Controller('/api/v1')
class Fruit {
// GET /api/v1/hello
@Get()
hello() {
}
}
```

以下方代码为例子,如果要处理当前Controller的跟路径,请使用Get('/')

```typescript
@Controller('/api/v1')
class Fruit {
// GET /api/v1/
@Get('/')
home() {
}
}
```

### 新增RestController修饰

1. 新增RestController修饰,这个修饰器为HttpController修饰器的子类,主要是HttpController的扩展
2. 基于RestController实现相关Restful 请求特性。

#### RESTful的独有特性

- 与常规HttpController不同,RestController将自动携带 Hypermedia,
API,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
比如访问 https://api.github.com/ 即可获得所有api 访问api.github.com/user,然后就得到了下面结果。

```json
{
"message": "Requires authentication",
"documentation_url": "https://docs.github.com/rest/reference/users#get-the-authenticated-user"
}
```

#### 具体能力

- 配置baseRoot对RestController的会产生影响,通过这个字段可以全局调整RESTful根路径。

```typescript
//config.default.ts
tegg:{
baseRoot:'/tegg'
}
```

此时会将rest默认的`/api`前缀覆盖为`/tegg`

```typescript
//config.default.ts
tegg:{
baseRoot:'/'
}
```

此时会将rest默认的`/api`前缀覆盖为`/`

- @RestController继承自HttpController,但是与Controller不同,如果path为缺省会根据当前的class name 并以复数的形式自动补全,会在当前根目录自动生成Hypermedia API。

```typescript
type RestControllerOptions {
docURL?:string,
version?:string,
protoName?: string,
controllerName?: string,
}
@RestController(path?: string, options?: RestControllerOptions)

```

以下方代码为例子,我们没有填写任何参数并且没有配置`baseRoot`字段,那么就会指向`/api/v1/fruits`

```typescript
@RestController()
class Fruit {
// GET /api/v1/fruit/apple
@List
apple() {}
}
```

下面我们假设进行请求

```bash
$ GET /api/v1/fruits
# 我们会得到

{
"apple": "/api/v1/fruits/apple"
"documentation_url": "/doc/v1/fruit"
}
```

```bash
$GET /api/v1
# 我们会得到

{
"fruit": "/api/v1/fruits"
"documentation_url": "/doc/v1"
}
```

基于Get 请求增加,额外的业务能力

`@Query`支持取出单条数据

```typescript
@Query()
foo(id:string):Promise {}
```

`@List` 支持取出所有数据,默认遵从RESTful风格支持常见参数过滤(可能需要配合ORM的能力)

1.支持 ?limit=10:指定返回记录的数量

2.支持 ?offset=10:指定返回记录的开始位置。

3.支持 ?page=2&per_page=100:指定第几页,以及每页的记录数。 4.根据函数的入参可以进行横向扩展,比如需要支持搜索

```typescript
@List()
listFoo(keyword:string):Promise> {}
```

剩余业务能力支持待补充

### 新增RpcController修饰

待调查: 主要调查方向GRPC, JSONRPC

### 其他资料与难点调研
[英文单词复数化](http://kuwamoto.org/2007/12/17/improved-pluralizing-in-php-actionscript-and-ror/)
[hypermedia 实现调研](https://github.com/ttahmouch/hypermedia)

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.