让我们来重新设计一下 koa-router

前言

koa-router 是目前用的比较多的 Koa 的路由中间件之一,前段时间由于作者没有精力继续维护而将其公开售卖。我们有些项目也用到了这个库,但是目前很多我们想要的特性都没有,比如生成接口文档。本身这个库代码实现还比较简单,因此综合考虑打算重写一个。

项目地址:https://github.com/d-band/koa...

特性:

  • 支持几乎所有的 koa-router 特性
  • 支持 params 校验
  • params 支持从 path, header, query, cookie 中获取
  • 支持 body parser
  • 支持 request body 校验
  • 支持参数类型自动转换
  • 支持自动生成 OpenAPI

简单例子:

index.js

import Koa from 'koa';
import Mapper from 'koa-mapper';
import * as service from './service';

const Mapper = new Mapper();

mapper.get('/users/:id/projects', {
  params: {
    id: { type: 'number' },
    status: { type: 'array<string>', in: 'query' },
    token: { type: 'string', in: 'header' }
  }
}, service.getProjects);

mapper.post('/users/:id/projects', {
  params: {
    id: { type: 'number' }
  },
  body: 'Project'
}, service.addProject);

mapper.schema('Project', {
  id: { type: 'number', required: true },
  name: { type: 'string', required: true },
  status: { type: 'array<Status>', required: true }
});

mapper.schema('Status', {
  id: { type: 'integer' },
  name: { type: 'string' }
}, {
  required: ['id', 'name']
});

app.use(mapper.routes());
app.use(mapper.allowedMethods());

app.listen(3000);

// open http://localhost:3000/openapi.json

service.js

export async function getProjects(ctx) {
  const { id, status, token } = ctx.params;

  await checkToken(id, token);

  ctx.body = await Project.findAll({
    where: {
      userId: id,
      status: { $in: status }
    }
  });
}

export async function addProject(ctx) {
  const { body } = ctx.request;

  ctx.body = await Project.create({
    ...body,
    userId: id
  });
}

路由定义:

mapper.get(path, [options], ...middlewares);
mapper.post(path, [options], ...middlewares);
mapper.put(path, [options], ...middlewares);
mapper.del(path, [options], ...middlewares);
...

options 为可选参数,包含:

  • name: 路由名称
  • params: 请求参数定义
  • body: 请求 Body 定义
  • 其他 OpenAPI 中 Operation Object 的参数

options.params 为请求参数定义,如:

params = {
  id: { type: 'number' },
  name: { type: 'string', in: 'query' },
  user: { type: 'User', in: 'query' }
}
  • type: 参数类型,包含基本类型(numberstringintegerdatetimedatetime),数组类型(array<string>),自定义类型(如 User),自定义数组类型(array<User>),多个类型(number|string
  • in: 参数来源,包含 path,header,query,cookie
  • 其他 OpenAPI 中 Parameter Object 的参数

自定义类型

mapper.define(schemaName, properties, options);
// or
mapper.schema(schemaName, properties, options);

支持类型组合,如:

mapper.schema('Status', {
  id: { type: 'integer' },
  name: { type: 'string' }
}, {
  required: ['id']
});
mapper.schema('Project', {
  id: { type: 'number', required: true },
  name: { type: 'string', required: true },
  status: { type: 'array<Status>', required: true }
});

支持继承,如:

mapper.schema('Model', {
  id: { type: 'number' },
  createdAt: { type: 'datetime' },
  updatedAt: { type: 'datetime' }
});
mapper.schema('User: Model', {
  name: { type: 'string' }
});

Body Parser

mapper.post('/users', {
  body: 'User'
}, (ctx) => {
  const { id, name } = ctx.request.body;
});

支持文件上传,如:

mapper.post('/uploadImage', {
  bodyparser: { multipart: true },
  body: {
    user: { type: 'number' },
    image: { type: 'file' }
  }
}, (ctx) => {
  const { user, image } = ctx.request.body;
});

结尾

目前 koa-mapper 刚发布,测试覆盖率达到 100%,有哪些有兴趣的小伙伴欢迎一起维护。

原文链接:segmentfault.com

上一篇:关于DOM操作是异步的还是同步的相关理解
下一篇:redux中applyMiddleware源码,中文注释

相关推荐

  • (原创)vue-router的Import() 异步加载模块问题的解决方案

    关注不迷路,如果解决了问题,留下个赞。 1、问题现象 2、出现问题的代码点 3、替代方案: 把import() 替换成如下: Promise.resolve().then(()=&...

    5 个月前
  • 阿里云centOS部署vue全家桶+node+koa2+mongo项目

    写在前面 文章有丢丢长,前端开发第一次部署项目,有问题请及时提出,以免误导其他童鞋,轻拍~, 更新系统 sudo yum update 安装mongo 1. 添加MongoDB源 在/etc/yum....

    2 年前
  • 重拾vue--vue-router进阶

    路由组件传参 HTML5 History模式 导航守卫 路由元信息 过渡效果 name="router",对应class中的router-enter &lt;transition-group ...

    2 年前
  • 通过编写一个路由中间件来学习 Koa

    混了四年的大学生活结束了,校招没有找到工作的我还面临着失业。没办法,只有临时抱抱佛脚看看能不能找个工作了。据说最近前端圈里不会 NodeJs 是不可能找到工作的,于是抱起了 NodeJs 里比较流行的...

    2 年前
  • 通过vue-router学习vue

    vue-router是vue官方支持,可以看做vue最佳实践本文大致梳理vue-router源码各个文件大体作用,不深入细节建议对照vue-router源码阅读 src/index.js 1. Vue...

    6 个月前
  • 通过koa2和Promise.race()构造一个超时取消的ajax。

    MDN上说: 你可以使用AbortController.AbortController()构造函数创建一个新的AbortController对象。 使用AbortSignal 对象完成与DOM请求的...

    2 年前
  • 适合初学者的koa2+mongodb初体验

    前言      笔者的前端开发已经有些时日了,对于node一直保留着最初的恐惧,倘若一座不可跨越的高山,思前想后终于迈出最后一步,踏入了开拓自己视野的新视界,希望在看这篇文章的你可以一起跟我动手尝试...

    1 年前
  • 踩坑记之基于Vue+Element+Koa实现云上存储

    前言最近在做项目等时候,需要处理图片,表格,文本等多种格式的文件到数据库,用传统等方法进行处理既繁琐又比较麻烦,所以第一次尝试使用云上存储等方式来实现。比较了阿里云和腾讯云之类的网站之后,最终选择七牛...

    5 个月前
  • 跨域cors 和 jsnop | koa 提供服务器 (实例前端 -后端演示)

    文章目的 验证一下对跨域的理解- 前端需要都需要配置 后端相应配置什么 首先跨域方式不止这两种 iframe.posetMessage form 表单也可。 ==== 项目地址 (https://gi...

    1 年前
  • 超轻量级web框架koa源码阅读

    koa是一个非常轻量的web框架,里面除了ctx和middleware之外什么都没有,甚至连最基本的router功能都需要通过安装其他中间件来实现。不过虽然简单,但是它却非常强大,仅仅依靠中间件机制就...

    2 年前

官方社区

扫码加入 JavaScript 社区