学习RESETful API和KOA

RESETful API设计最佳实践

请求规范

请求应该包含URL、HTTP方法、请求体等。

  • URL使用名词,尽量使用复数;
  • URL使用嵌套表示关联关系,如/users/12/repos/5
  • 使用正确的方法:GET/POST/PUT/DELETE

响应规范

  • 如果是分页,应该包含当前页数和每一页的数量:分页 page=2&per_page=100
  • 状态码:2开头正确 3表示重定向 4表示客户端错误 5代表服务端错误
  • 错误处理:返回错误信息。

安全

  • HTTPS
  • 鉴权
  • 限流:在HTTP头加上了字段记录请求次数,如果超过规定的额度就会报403的错误。

安装和使用KOA

npm init
cnpm i koa --save

新建index.js

const Koa = require('koa');
const app = new Koa();

app.use(()=>{
  console.log("Hello world");
})

app.listen(3000);

运行node index.js,打开http://localhost:3000/页面显示Not Found,在终端打印了Hello world

认识中间件

修改上面的例子为下:

const Koa = require('koa');
const app = new Koa();
const test = ()=>{
    console.log("Hello world");
}
app.use(test);
app.listen(3000);

重新运行node index.js,刷新网页,结果还是一样。这里app.use()的内容就是中间件。我们可以使用多个中间件,使用多个中间件的时候我们需要使用next

const Koa = require('koa');
const app = new Koa();

const test1 = (ctx,next)=>{
  console.log("Hello world");
  next();
}

const test2 = (ctx,next)=>{
  console.log("Hello China");
  next();
}

app.use(test1);
app.use(test2);

app.listen(3000);

ctx是上下文,next执行下一个中间件。打印结果:

Hello world
Hello China

ctx的理解:ctx可以帮助你在多个中间件流转数据。

// 在test1中间件中
ctx.str = 'Hello world';
// 在test2中间件中可以读取
console.log(ctx.str);

自动更新nodemon

每次修改完代码又要重新启动很影响效率。

cnpm i nodemon --save-dev

以后运行就直接nodemon+文件名

nodemon index.js

简化命令,在package.jsonscript新增命令

"start":"nodemon index.js"

 

rest风格api 命名_rest风格api 命名

运行npm start即可。

洋葱模型

首先我们来看一个例子:

const Koa = require('koa');
const app = new Koa();

app.use((ctx,next)=>{
  console.log("我是1");
  next();
  console.log("我是1");
});
app.use((ctx,next)=>{
  console.log("我是2");
  next();
  console.log("我是2");
});
app.use((ctx,next)=>{
  console.log("我是3");
  next();
  console.log("我是3");
});

app.listen(3000);

打印的结果是:

rest风格api 命名_分页_02

这样的输出就是洋葱模型。从test1->test2进去,从test2->test1出来。

rest风格api 命名_rest风格api 命名_03

koa的开发就是采用了洋葱模型。但是如果某个中间件中使用了异步请求(这里我们用setTimeout来模拟)

const Koa = require('koa');
const app = new Koa();

app.use((ctx,next)=>{
  console.log("我是1");
  next();
  console.log("我是1");
});
app.use((ctx,next)=>{
  console.log("我是2");
  next();
  console.log("我是2");
});
app.use((ctx,next)=>{
  setTimeout(()=>{
    console.log("我是3");
  },1000)
  next();
  console.log("我是3");
});

app.listen(3000);

此时打印的结果为:

rest风格api 命名_rest风格api 命名_04

koa如何确保洋葱模型呢,经过研究源码我们可以知道,koa在next上返回了一个promise对象。

app.use((ctx,next)=>{
  const res = next();
  console.log(res);
});

rest风格api 命名_中间件_05

熟悉async/await的话你就会发现,我们可以使用async/await来实现异步条件下的洋葱模型。

const Koa = require('koa');
const app = new Koa();

app.use(async (ctx,next)=>{
  console.log("我是1");
  await next();
  console.log("我是1");
});
app.use(async (ctx,next)=>{
  console.log("我是2");
  await next();
  console.log("我是2");
});
app.use(async (ctx,next)=>{
  console.log("我是3");
  await next();
  console.log("我是3");
});

app.listen(3000);

rest风格api 命名_HTTP_06

 

资料参考: (浅析koa的洋葱模型实现)