一. RESTful(Representational State Transfer)风格API:
1. 客服服务端(Client-Server)
关注点分离,服务端专注数据存储,提升了简单性,前端专注用户界面,提升了可移植性
2. 无状态(Stateless)
每次请求必须包括所有信息,不能依赖上下文信息,客户端保留所有会话信息,服务端不再保留会话信息
3. 缓存(Cache)
所有信息必须标记为可缓存或不可缓存
4. 统一接口(Uniform Interface)
接口设计尽可能统一,接口与实现解耦
5. 分层系统(Layered System)
每一层只知道相邻的一层,每一层负责不同的功能安全,负载均衡
6. 按需代码
RESTful风格最佳例子:https://developer.github.com/v3/
二.koa基础使用
1.自定义路由
koa所需工具:nodemon自动重启
记得取package.json里写脚本:"start":"nodemon index.js",
断点调试和查看官网的api:ctx.url ctx.status ctx.method ctx.body
const Koa = require("koa")
const app = new Koa()
app.use(async (ctx) => {
if (ctx.url === '/') {
//处理不同的url
ctx.body = "这是主页 "
} else if (ctx.url === "/user") {
//处理不同的方法
if (ctx.method === "GET") {
ctx.body = "这是用户列表页"
} else if (ctx.method === "POST") {
ctx.body = "创建用户"
} else {
//方法不允许
ctx.status = 405
}
} else if (ctx.url.match(/\/user\/\w+/)) {
// 解析请求参数
const userId = ctx.url.match(/\/user\/(\w+)/)[1]
ctx.body = `这是用户${userId}`
} else {
ctx.status = 404
}
})
app.listen(3000)
2.使用koa-router,不用自定义路由
koa-router实现路由
获取HTTP请求参数:
- 获取query(ctx.query). ?q=keyword
- 获取body(koa-bodyparser||koa-body)
- 获取header(ctx.header). Accept,Cookie
- 获取router params(ctx.params). /users/:id
发送HTTP响应:
- 发送status(ctx.status)
- 发送body(ctx.body)
- 发送header(ctx.set("Allow","get","post"))Allow Content-type
- 实现用户的增删改查(get获取用户,post新建返回新建用户,put全部更新,patch局部更新,delete删除返回204,options显示支持什么访问方法)
常用状态码:
204:删除用户后返回,表示成功状态响应代码指示请求已成功,但没有内容返回
200:响应成功,内容返回
500:运行时错误
404:找不到
412:先决条件失败
422:无法处理的实体,参数格式不对
const Koa = require("koa")
const Router = require("koa-router")
const app = new Koa()
const router = new Router()
//前缀
const userRouter = new Router({ prefix: "/user" })
const koaBody = require("koa-body")
const parser = require("koa-bodyparser")
//多中间件
const auth = async (ctx, next) => {
// if(ctx.url !== "/user"){
// //没有权限
// ctx.throw(401)
// }
await next( )
}
router.get("/", (ctx) => {
ctx.body = "这是主页"
})
//处理不同的url
userRouter.get('/', auth, (ctx) => {
ctx.body = "这是用户列表"
})
//处理不同的方法 post新建用户 返回新建的用户
userRouter.post("/", auth, (ctx) => {
ctx.body = "创建用户"
})
//解析请求参数 get查列表 返回列表
userRouter.get("/:id", auth, (ctx) => {
//设置header响应头
ctx.set("Allow","GET,POST")
ctx.body = `这是用户${ctx.params.id}列表 `
})
//put修改 返回修改的用户
userRouter.put("/:id", (ctx) => {
ctx.body = `这是用户${ctx.params.id}`
})
//delete删除 返回实体,但是成功
userRouter.delete("/:id", (ctx) => {
ctx.status = 204
})
//注册中间件
app.use(parser( ))
app.use(router.routes())
app.use(userRouter.routes())
//响应options方法请求,告诉他所支持的请求方法
//405方法不允许,支持但没写。501方法无法实现,不存在
app.use(userRouter.allowedMethods())
app.listen(3000)
//http请求参数:
//Query String 如?q=keyword(可选)
//Router Params 如/user/:id(必传)
//Body,如json,form等conten-type里面会写到
//Header,如accept,cookie,jwt等
//发送http响应:
//发送status。如200/400等
//发送body,如json等
//发送header,如allow,content-type等
//1.每个资源的控制器尽量发在不同的文件里
//2.尽量使用类+类的形式编写控制器
//3.严谨的错误处理
3.错误处理和更加合理的目录结构
错误处理:
ctx.throw(422,'文本信息')
koa-json-error:记得隐藏堆栈信息,在生产环境的时候
koa-parameter:校验参数ctx.verifyParams({name:{type:"string",required:true}})
const Koa = require("koa")
const bodyParser = require("koa-bodyparser")
const app = new Koa()
const routing = require("./routes")
const error = require("koa-json-error")
const parameter = require('koa-parameter')//校验参数
//自定义的错误处理,无法捕获404信息
// app.use(async (ctx, next) => {
// try {
// await next()
// } catch (error) {
// //断点
// ctx.status = error.status || error.statusCode || 500
// //返回json格式
// ctx.body = {
// message: error.message
// }
// }
// })
app.use(error({
//定制返回格式
postFormat: (e, { stack, ...rest }) => {//原生的error,应该返回的格式
// "start": "export NODE_ENV='production'&& nodemon app",
return process.env.NODE_ENV === "production" ? rest : { stack, ...rest }
}
}))//koa-json-error中间价处理错误,404,412,500
app.use(bodyParser())//解析请求体
app.use(parameter(app))//校验参数,传入app,进行全局的使用,全局方法,比如在create方法中
routing(app)
app.listen(3000, () => { console.log("程序在3000端口启动了") })
//异常状况有哪些
//1.运行是错误,服务器内部的错误500
//2.逻辑错误,找不到404,先决条件失败412,无法处理的实体(参数格式不对422)
// 为什么要使用错误处理
//1.防止程序挂掉
//2.告诉用户信息
//3.便于开发者调试
目录结构
网友评论