Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Cyberhan123 opened this issue Dec 16, 2021 · 14 comments
Open

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

Cyberhan123 opened this issue Dec 16, 2021 · 14 comments

Comments

@Cyberhan123
Copy link

Cyberhan123 commented Dec 16, 2021

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

背景

参照: 提供更加简单化请求方法的修饰器的讨论

思路

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

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

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

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

新增baseRoot

  • config新增baseRoot能力

    tegg:{
      baseRoot:string
    }
  • 通过这个字段可以全局调整路由根路径

    //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:

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

新增Controller下Http Method修饰器

  • 新的Http Method 会跟 HTTPMethodEnum 的枚举保持一致,包含 GETPOSTPUTDELETEPATCHOPTIONSHEAD

  • 所有的方法入参暂时定为继承自HTTPMethod,以GET为例:

    Get(path?: string, priority?: number)
  • 与HTTPMethod不同的是Get第一个入参为可选,如果Get的path入参为空时, 可以通过检索Handler Function 名称自动匹配路径。 下面以GET为例:

    @Controller('/api/v1')
    class Fruit {
        // GET /api/v1/hello
        @Get()
        hello() {
        }
    }

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

    @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,然后就得到了下面结果。

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

具体能力

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

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

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

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

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

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

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

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

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

    下面我们假设进行请求

    $ GET /api/v1/fruits
    # 我们会得到
    
    {
      "apple": "/api/v1/fruits/apple"
      "documentation_url": "/doc/v1/fruit"
    }
    $GET /api/v1 
    # 我们会得到
    
    {
      "fruit": "/api/v1/fruits"
      "documentation_url": "/doc/v1"
    }

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

    @Query支持取出单条数据

     @Query()
     foo(id:string):Promise <Foo> {}

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

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

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

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

@List()
listFoo(keyword:string):Promise<Array<Foo>> {}

剩余业务能力支持待补充

新增RpcController修饰

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

其他资料与难点调研

英文单词复数化
hypermedia 实现调研

@Cyberhan123
Copy link
Author

Cyberhan123 commented Dec 16, 2021

cc @killagu ,我把咱们讨论的问题进行了一下小结,在整理的时候发现了一点问题,我查了一下阮一峰的RESTful描述,如果要是严格按照这个描述的话,RestController的HttpMethod是否是一个就够了?我们是否要在这一个Handler里处理全部HttpMethod?

@killagu
Copy link
Contributor

killagu commented Dec 16, 2021

RestController 只有一个 http method 是不够的,每个动词都代表了不同的行为。不能混在一个 method 里的。

@killagu
Copy link
Contributor

killagu commented Dec 16, 2021

@Controller('/api/v1')
class Fruit {
  // GET /api/v1/hello
  @Get()
  Hello() {}
}
  • Hello 方法名是否应该小写?
@Controller('/api/v1')
class Fruit {
  // GET /api/v1/
  @Get()
  Index() {}
}

Index 会被替换为 /。这个在方法名作为 path 的规则上又加了一个规则,有些复杂了,不如显示的写 @Get('/') 来的直接。

@Cyberhan123
Copy link
Author

@Controller('/api/v1')
class Fruit {
  // GET /api/v1/hello
  @Get()
  Hello() {}
}
  • Hello 方法名是否应该小写?
@Controller('/api/v1')
class Fruit {
  // GET /api/v1/
  @Get()
  Index() {}
}

Index 会被替换为 /。这个在方法名作为 path 的规则上又加了一个规则,有些复杂了,不如显示的写 @Get('/') 来的直接。

嗯,Hello的大小写我修改一下,第二个问题说的也有道理,确实是这样

@Cyberhan123
Copy link
Author

Cyberhan123 commented Dec 17, 2021

RestController 只有一个 http method 是不够的,每个动词都代表了不同的行为。不能混在一个 method 里的。

这个能不能具体说一下,因为我平时使用RESTful比较少

@killagu
Copy link
Contributor

killagu commented Dec 20, 2021

rest 是以资源为维度来访问的,比如 POST 是创建一个资源, GET / 获取列表, GET /:id 是获取一个字端,PUT, DELETE 都有其含义。

@Cyberhan123
Copy link
Author

rest 是以资源为维度来访问的,比如 POST 是创建一个资源, GET / 获取列表, GET /:id 是获取一个字端,PUT, DELETE 都有其含义。

如果是这样的话好像不需要RestController了吧,只需要把 path传入对应的HttpMethod就可以了

@killagu
Copy link
Contributor

killagu commented Dec 21, 2021

意义还是有的,也是简化。
比如说 list,get 可以写成

@RestController()
class Resource {
  @List()
  listFoo(): Promise<Array<Foo>> {}

  @Get()
  getFoo(id: string): Promise<Foo> {}
}

@Cyberhan123
Copy link
Author

Cyberhan123 commented Dec 21, 2021

我去学习了一下相关内容,补充了一下RFC内容,麻烦帮忙康康有没有啥问题@killagu ☺️

@killagu
Copy link
Contributor

killagu commented Dec 22, 2021

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

按照 rest 风格,这个作为 /api/v1/fruits 更好,应该以资源为核心,与方法名无关。

新增的 controller 注解,可以补充一下如何 import。

@killagu
Copy link
Contributor

killagu commented Dec 27, 2021

@Cyberhan123 可以先来写一版 http 的。RFC 看起来不错

@Cyberhan123
Copy link
Author

Cyberhan123 commented Dec 27, 2021

@Cyberhan123 可以先来写一版 http 的。RFC 看起来不错

好的~~,这个RFC也会不断完善的

@Cyberhan123
Copy link
Author

最近比较忙,不过我会继续的,不会咕咕

@yuu2lee4
Copy link

yuu2lee4 commented Apr 6, 2023

没有进展了吗

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants