English | 简体中文
一个简单、快速、轻量的 HTTP 服务框架,专为 API 而生
- API 而生 专为 API 开发使用,无需考虑复杂的页面数据渲染逻辑
- 轻量极简 不到 10K、不依赖第三方库、不过度封装
- 模式灵活 支持微服务、Serverless 模式、Context 可自由扩展
- 文档友好 自动生成接口文档、自动生成前端接口代码
- TypeScript 全部使用 TypeScript 编写,类型约束、IDE 友好
- Deno 支持在 Deno 下运行(todo)
- 受 koa 启发,完善 Context 生成机制
- 受 koa-router 启发,完善路由生成机制
- 受 koa-bodyparser 启发,完善请求体处理机制
- 受 egg 启发,完善 Context 扩展机制
- 以 swagger-ui 为基础,完成接口文档的自动生成
-
第一版 coajs:于 2019 年发布的第一个版本,本身属于第三方类库的整合。从多个线上项目中抽离出来,以方便部署更新为目的作为单独的库。随着不断迭代,添加的东西越来越多,
coajs
变得越来越臃肿,已经不适合轻量级小项目使用。迭代 114 个版本后停止维护 -
第二版 coa-serve:针对第一版出现的臃肿问题,基于
coajs
将其化整为零,分别将基础组件和核心组件抽离为单独的库,并将其开源,同时对文档生成机制、路由检索、系统环境配置等机制做了很多的优化。目前已经稳定,线上所有的coajs
项目均已经迁移到coa-serve
来 -
第三版 coa-http:也就是目前的版本。随着不断迭代,接口对外提供服务的方式已经不限于
http
了,将tcp
、websocket
等服务直接整合到coa-serve
中并不优雅。此外,随着笔者的认知进步,koa
全家桶也并不是最优的选择。故计划将coa-serve
拆解,分别重构为 coa-http、coa-tcp、coa-websocket 等。本项目coa-http
正是这三者之一,目前仍在公测阶段
请确保在操作系统上安装了最新稳定版的 Node.js
mkdir <project-name>
cd <project-name>
yarn add coa-http
yarn add typescript tsc-watch @types/node -D
gateway # 网关层
├─ index.ts # 网关入口
├─ debug # debug模块
│ └─ test.ts # debug模块的路由
service # 服务层
├─ index.ts # 具体服务的实现
package.json
tsconfig.json
在 gateway/index.ts
中写入代码
import { CoaContext, CoaHttp } from 'coa-http'
export const http = new CoaHttp(CoaContext)
http.start().then(() => {
// 做一些启动后的事情
})
在 gateway/debug/test.ts
中写入代码
import { http } from '..'
http.router.register('调试', {
'/debug/test/hello': {
options: {
method: 'GET',
name: '你好世界',
},
async handler() {
return { result: 'hello,world!' }
},
},
})
在 tsconfig.json
中写入配置
{
"compilerOptions": {
"strict": true,
"module": "CommonJS",
"target": "ESNext",
"baseUrl": ".",
"outDir": "node_run",
"sourceMap": true
},
"include": ["gateway", "service"]
}
在 package.json
文件的 scripts
节点中加入 dev
{
"scripts": {
"dev": "HOST=3000 NODE_PATH=node_run tsc-watch --onSuccess 'node node_run/gateway'"
}
}
yarn dev
看到类似下面的运行结果,说明启动成功。修改代码后,会自动重启服务。
Found 0 errors. Watching for file changes.
[server] Booting...
[server] Startup successful in: 5.399953 ms
[server] Listening on: http://localhost:3000/gw/doc
此时,在浏览器中打开 http://localhost:3000/gw/doc
,可以直接查看接口文档。
使用 http.router.register
方法注册路由,一个最简单的路由如下所示。
http.router.register('调试', {
'/debug/test/hello': {
options: {
name: '测试', // 名称
method: 'GET', // 调用方法
param: {
title: { required: true, description: '标题参数', example: 'test' },
},
},
async handler(ctx) {
// 获取所有的query参数
const query = ctx.request.query
// 获取title参数
const title2 = ctx.get('title')
// 使用json的格式返回结果
return { query, title }
},
},
})
每注册一批路由,会自动划分为一组。在业务开发时,可以将每个模块拆分为文件单独分组。
// gateway/module-a.ts
http.router.register('A模块', {
'/api/module-a/action-1': {
/* ... */
},
'/api/module-a/action-2': {
/* ... */
},
})
// gateway/module-b.ts
http.router.register('B模块', {
'/api/module-b/action-1': {
/* ... */
},
'/api/module-b/action-2': {
/* ... */
},
'/api/module-b/action-3': {
/* ... */
},
})
和 koa
类似,handler
方法包含一个 ctx
参数。ctx
是一个 Context
的实例,包含当前请求过程中上下文所有信息。
http.router.register('调试', {
'/debug/test/hello': {
options: {
method: 'GET',
name: '你好世界',
},
async handler(ctx) {
// ctx 包含所有上下文信息
return { result: 'hello, world!' }
},
},
})
coa-http
原生支持 json
和 text
格式的响应结果。但有时候我们需要自定义响应格式,比如流的形式。下面的例子展示了将网络上的资源通过流的形式直接返回。
http.router.register('调试', {
'/debug/test/proxy': {
options: {
method: 'GET',
name: '流的形式返回结果',
param: {
url: { required: true, description: '网络资源路径', example: 'http://github.com' },
},
},
async handler(ctx) {
// 获取url参数
const url = ctx.required('url', '')
// 获取网络上的资源流
const { data, status, headers } = await axios.get(url, { responseType: 'stream' }).catch((e) => e.response)
// 设置响应信息
ctx.res.statusCode = status
ctx.res.setHeader('Content-Type', headers['content-type'])
// 网络上的资源流通过管道方式流入响应流
data.pipe(ctx.res)
// 自定义响应结果,coa-http将不会进行后续的响应处理
return ctx.custom()
},
},
})