RESTful API具体是什么样子的
- 基本的URI如 http://github.com/user
- 标准的HTTP方法
- 传输的数据媒体类型,如JSON,XML
请求设计规范
- URI使用名词,尽量用复数,如/users
- URL使用嵌套表示关联关系,如/users/12/repos/5
- 使用正确的HTTP方法,如GET/POST/PUT/DELETE
- 不符合CRUD的情况:POST/action/子资源
响应设计规范
- 查询
- 分页
- 字段过滤
- 状态码
- 错误处理
安全
- HTTPS
- 鉴权
- 限流
HTTP OPTIONS方法
- 检测服务器所支持的请求方法
- CORS中的预检请求
allowedMethods方法
- 响应
options方法,告诉它所支持的请求方法 - 相应地返回
405(不允许,还没写,可以实现)和501(没实现,服务端没法实现)
app.use(userRouter.allowedMethods())
RESTful API最佳实践——增删改查应该返回什么响应
204 No Content
成功,但是没有返回内容
控制器简介
- 拿到路由分配的任务,并执行
- 在Koa中是一个中间件
为什么要用控制器
获取HTTP请求参数
Query String,如q?=keyword(可选)Router Params,如/users/:id(必选)Body请求体,如{name: "李雷"}Header,如Accept、Cookie
处理业务逻辑
发送HTTP响应
- 发送
Status,如200/400等 - 发送
Body,如{name: "李雷"} - 发送
Header,如Allow、Content-Type
编写控制器的最佳实践
- 每个资源的控制器放在不同的文件里
- 尽量使用类+类方法的形式编写控制器
- 严谨的错误处理
获取HTTP请求参数
学习断点调试
获取query
ctx.query
获取router params
- 路由为
/user/:id时,使用ctx.params.id来获取路由参数。
获取body
ctx.request.body
获取header
###异常状况的种类
- 运行时错误,都返回500
- 逻辑错误,如找不到返回404、先决条件失败(412)、无法处理的实体(参数格式不对,422)等
Session简介
session的优势
- 相比
JWT,最大的优势就在于可以主动清除session了。 session保存在服务器端,相对比较安全。- 结合
cookie使用,较为灵活,兼容性较好。
session的劣势
cookie+session在跨域场景表现并不好。- 如果是分布式部署,需要做多机共享
session机制。 - 基于
cookie的机制很容易被CSRF。 - 查询
session信息可能会有数据库查询操作。
session相关的概念介绍
session:主要存放在服务器端,相对安全。cookie:主要存放在客户端,并且不是很安全。sessionStorage:仅在当前回话下有效,关闭页面或浏览器后被清除。localStorage:除非被清除,否则永久保存。
JWT简介
什么是JWT
JSON Web Token是一个开放标准(RFC 7519)。- 定义了一种紧凑且独立的方式,可以将各方之间的信息作为
JSON对象进行安全传输。 - 该信息可以验证和信任,因为是经过数字签名的。
JWT的构成
- 头部(
Header)typ:token的类型,这里固定JWT。alg:使用的hash算法,例如:HMAC SHA256或者RSA。
- 有效载荷(
Payload)- 存储需要传递的信息,如用户
ID用户名等。 - 还包含元数据,如过期时间、发布人。
- 与
Header不同,Payload可以加密。
- 存储需要传递的信息,如用户
- 签名(
Signature)- 对
Header和Payload部分进行签名。 - 保证
Token在传输的过程中没有被篡改。
- 对
JWT对比Session
- 可拓展性。
JWT优于Session - 安全性。
- RESTful API。
JWT属于无状态所以使用JWT。 - 性能。可能有大量用户信息,影响每一个
http请求。 - 时效性。
JWT只能过期之后才能失效,而session能在服务端进行失效处理。
上传图片需求分析
图片种类
- 用户头像
- 封面图片
- 问题和回答中的图片
- 话题图片
- 其它
功能
- 基础功能:上传图片,生成图片链接
- 附加功能:限制上传图片的大小与类型、生成高中低三种分辨率的图片链接、生成
CDN
用户个人资料Schema设计
- 性别
// enum 表示可枚举
gender: { type: String, enum: ['male', 'female'], default: 'male', required: true }
- 地区
location: { type: [type: String] } // 这样表示字符串数组