# 第2节 以豆瓣网为例, 讲解restful api设计规范
* **什么是restful api**
* 目前比较成熟的一套互联网应用程序的API设计理论豆瓣电影api
## [豆瓣电影api](https://developers.douban.com/wiki/?title=movie_v2)
1. 应该尽量将API部署在专用域名之下
http://api.douban.com/v2/user/1000001?apikey=XXX
2. 应该将API的版本号放入URL
http://api.douban.com/v2/user/1000001?apikey=XXX
3. 在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数。
http://api.douban.com/v2/book/:id (获取图书信息)
http://api.douban.com/v2/movie/subject/:id (电影条目信息)
http://api.douban.com/v2/music/:id (获取音乐信息)
http://api.douban.com/v2/event/:id (获取同城活动)
4. 对于资源的具体操作类型,由HTTP动词表示。常用的HTTP动词有下面四个(对应增/删/改/查)。
GET(select):从服务器取出资源(一项或多项)。
eg. 获取图书信息 GET http://api.douban.com/v2/book/:id
POST(create):在服务器新建一个资源。
eg. 用户收藏某本图书 POST http://api.douban.com/v2/book/:id/collection
PUT(update):在服务器更新资源(客户端提供改变后的完整资源)。
eg. 用户修改对某本图书的收藏 PUT http://api.douban.com/v2/book/:id/collection
DELETE(delete):从服务器删除资源。
eg. 用户删除某篇笔记 DELETE http://api.douban.com/v2/book/annotation/:id
5. 如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果
?limit=10:指定返回记录的数量
eg. 获取图书信息 GET http://api.douban.com/v2/book/:id?limit=10
6. 服务器向用户返回的状态码和提示信息
每个状态码代表不同意思, 就像代号一样
2系 代表正常返回
4系 代表数据异常
5系 代表服务器异常
| 错误码 | 错误信息 | 含义 | 状态码 |
| --- | --- | --- | --- |
| 6000 | book_not_found | 图书不存在 | 404 |
| `6002` | `unauthorized_error` | 没有修改权限 | 403 |
| 6004 | review_content_short(should more than 150) | 书评内容过短(需多于150字) | 400 |
| 6006 | review_not_found | 书评不存在 | 404 |
| 6007 | not_book_request | 不是豆瓣读书相关请求 | 403 |
| 6008 | people_not_found | 用户不存在 | 404 |
| 6009 | function_error | 服务器调用异常 | 400 |
| 6010 | comment_too_long(should less than 350) | 短评字数过长(需少于350字) | 400 |
| 6011 | collection_exist(try PUT if you want to update) | 该图书已被收藏(如需更新请用PUT方法而不是POST) | 409 |
| 6012 | invalid_page_number(should be digit less than 1000000) | 非法页码(页码需要是小于1000000的数字) | 400 |
| 6013 | chapter_too_long(should less than 100) | 章节名过长(需小于100字) | 400 |
## 接口安全
1. API的身份认证应该使用OAuth 2.0框架。
2. 技术团队自己约定的规则
增加两个参数 `time`, `token`
`token`为时间戳加密后的字符串, 加密规则只有你们技术团队自己知道
time为时间戳, 用于判断接口请求是否超时