├── Makefile ├── src ├── appendix │ ├── README.md │ └── reference.md ├── restful_tool │ ├── README.md │ ├── test_tool.md │ └── framework_lib.md ├── assets │ ├── favicon.ico │ └── img │ │ ├── have_state.png │ │ ├── stateless.png │ │ ├── postman_debug_api.png │ │ ├── create_new_md_preview_1.png │ │ ├── create_new_md_preview_2.png │ │ ├── postman_generated_api_doc.png │ │ ├── pycharm_restful_api_tool.png │ │ ├── some_admin_web_list_page.png │ │ ├── swagger_generated_api_doc.png │ │ ├── youdao_markdown_preview_1.png │ │ ├── youdao_markdown_preview_2.png │ │ ├── youdao_markdown_explain_preview_1.png │ │ └── youdao_markdown_explain_preview_2.png ├── restful_experience │ ├── README.md │ ├── resp_data_style.md │ ├── bad_design.md │ ├── experience_other.md │ └── pagination.md ├── restful_rule │ ├── README.md │ ├── hateoas.md │ └── rule.md ├── restful_doc │ ├── use_swagger.md │ ├── README.md │ ├── use_postman.md │ └── use_markdown.md ├── SUMMARY.md ├── restful_intro │ ├── README.md │ └── example.md └── README.md ├── .gitignore ├── README_current.json ├── book_current.json ├── README.md └── book.json /Makefile: -------------------------------------------------------------------------------- 1 | include ../../common/gitbook_makefile.mk -------------------------------------------------------------------------------- /src/appendix/README.md: -------------------------------------------------------------------------------- 1 | # 附录 2 | 下面列出相关参考资料。 3 | 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | output/ 3 | debug/ 4 | 5 | *.zip 6 | 7 | .DS_Store 8 | -------------------------------------------------------------------------------- /src/restful_tool/README.md: -------------------------------------------------------------------------------- 1 | # RESTful API工具和库 2 | 3 | 下面介绍和RESTful API开发、设计时相关的一些工具、库。 4 | -------------------------------------------------------------------------------- /src/assets/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/favicon.ico -------------------------------------------------------------------------------- /src/restful_experience/README.md: -------------------------------------------------------------------------------- 1 | # RESTful API的心得和经验 2 | 3 | 此处把之前折腾过的RESTful的一些心得和经验整理出来,供参考。 4 | -------------------------------------------------------------------------------- /src/restful_rule/README.md: -------------------------------------------------------------------------------- 1 | # RESTful API通用设计规则 2 | 3 | 对于RESTful的API设计,有些通用的设计规则。其实也可以叫做HTTP的各种方法的典型用法。 4 | -------------------------------------------------------------------------------- /src/assets/img/have_state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/have_state.png -------------------------------------------------------------------------------- /src/assets/img/stateless.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/stateless.png -------------------------------------------------------------------------------- /src/assets/img/postman_debug_api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/postman_debug_api.png -------------------------------------------------------------------------------- /src/assets/img/create_new_md_preview_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/create_new_md_preview_1.png -------------------------------------------------------------------------------- /src/assets/img/create_new_md_preview_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/create_new_md_preview_2.png -------------------------------------------------------------------------------- /src/assets/img/postman_generated_api_doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/postman_generated_api_doc.png -------------------------------------------------------------------------------- /src/assets/img/pycharm_restful_api_tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/pycharm_restful_api_tool.png -------------------------------------------------------------------------------- /src/assets/img/some_admin_web_list_page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/some_admin_web_list_page.png -------------------------------------------------------------------------------- /src/assets/img/swagger_generated_api_doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/swagger_generated_api_doc.png -------------------------------------------------------------------------------- /src/assets/img/youdao_markdown_preview_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/youdao_markdown_preview_1.png -------------------------------------------------------------------------------- /src/assets/img/youdao_markdown_preview_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/youdao_markdown_preview_2.png -------------------------------------------------------------------------------- /src/assets/img/youdao_markdown_explain_preview_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/youdao_markdown_explain_preview_1.png -------------------------------------------------------------------------------- /src/assets/img/youdao_markdown_explain_preview_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/crifan/http_restful_api/HEAD/src/assets/img/youdao_markdown_explain_preview_2.png -------------------------------------------------------------------------------- /README_current.json: -------------------------------------------------------------------------------- 1 | { 2 | "latestVersion": "v3.0", 3 | "lastUpdate": "20190530", 4 | "gitRepoName": "http_restful_api", 5 | "bookName": "HTTP后台端:RESTful API接口设计", 6 | "bookDescription": "整理过[HTTP知识总结](http://book.crifan.com/books/http_summary/website)后,继续去整理`HTTP`的**后台**相关的技术。在服务器后台进行设计API接口时,目前最流行的风格(原则/标准/规范)就是`RESTful`,常简称为`REST`接口。" 7 | } -------------------------------------------------------------------------------- /src/restful_doc/use_swagger.md: -------------------------------------------------------------------------------- 1 | # 用Swagger写(设计API接口的同时就可以生成出)API文档 2 | 3 | 效果: 4 | [API Development Tools | Swagger Editor | Swagger](https://swagger.io/swagger-editor/) 5 | 6 | ![](../assets/img/swagger_generated_api_doc.png) 7 | 8 | 详见: 9 | 【整理】swagger OpenAPI 10 | 11 | * 优点: 12 | * 设计API接口的同时就是编写好了API文档 13 | * 因为有对应的工具可以直接生成API文档 14 | * 另外可以同时生成服务器端和客户端的代码 15 | * 剩下的只需要自己编写业务逻辑即可,支持N多种编程语言 16 | * 美观 17 | * 生成的API文档层次够清晰,够美观 18 | * 缺点: 19 | * 必须用swagger去设计和编写API文档 20 | 21 | -------------------------------------------------------------------------------- /src/restful_doc/README.md: -------------------------------------------------------------------------------- 1 | # 如何写API接口文档 2 | 3 | 如果你是后台API开发人员,往往会为了写清晰的API接口文档而发愁 4 | 此处,自己的建议和经验是: 5 | * 方法1: 用`markdown`写API文档 6 | * 方法2: 用[`Postman`](http://book.crifan.com/books/api_tool_postman/website)生成API文档 7 | * 方法3: 用`Swagger`写(设计API接口的同时就可以生成出)API文档 8 | * 并可生成对应的后台和前端的代码 9 | * 剩下只需要编写业务逻辑代码即可 10 | 11 | 后来发现其他还有一些API文档工具,比如: 12 | * [docute](https://github.com/egoist/docute) 13 | * [ShowDoc](https://www.showdoc.cc/) 14 | * [小幺鸡 接口文档管理工具](http://www.xiaoyaoji.cn/) 15 | * 也支持API接口调试 16 | 17 | 下面详细介绍这些写API文档的不同方法。 -------------------------------------------------------------------------------- /src/restful_tool/test_tool.md: -------------------------------------------------------------------------------- 1 | # RESTful的API测试工具 2 | 3 | ## Postman {#postman} 4 | 5 | 详见另外的教程:[API开发利器:Postman](http://book.crifan.com/books/api_tool_postman/website) 6 | 7 | ## PyCharm中的Restful API测试工具 {#pycharm-restful-api} 8 | 9 | ![](../assets/img/pycharm_restful_api_tool.png) 10 | 11 | 详见:【整理】flask restful api 测试工具 12 | 13 | ## Chrome插件:`Advanced REST client` {#chrome-plugin-advanced-rest-client} 14 | 15 | 详见:[[记录]chrome的websocket插件:Advanced REST client](https://www.crifan.com/chrome_websocket_plugin_advanced_rest_client/) 16 | -------------------------------------------------------------------------------- /book_current.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "HTTP后台端:RESTful API接口设计", 3 | "description": "总结HTTP后台方面的RESTful API方面的知识", 4 | "pluginsConfig": { 5 | "github-buttons": { 6 | "buttons": [ 7 | { 8 | "repo": "http_restful_api" 9 | } 10 | ] 11 | }, 12 | "sitemap-general": { 13 | "prefix": "https://book.crifan.com/gitbook/http_restful_api/website/" 14 | }, 15 | "toolbar-button": { 16 | "url": "http://book.crifan.com/books/http_restful_api/pdf/http_restful_api.pdf" 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/restful_doc/use_postman.md: -------------------------------------------------------------------------------- 1 | # 用Postman生成API文档 2 | 步骤: 3 | 1. Collection 4 | 2. 鼠标移动到某个Collection 5 | 3. 点击 三个点 6 | 4. Publish Docs 7 | 5. Publish 8 | 6. Public URL 9 | 7. 别人打开这个Public URL即可查看API文档 10 | 11 | 效果: 12 | 13 | ![](../assets/img/postman_generated_api_doc.png) 14 | 15 | 详见教程:[API开发利器:Postman](http://book.crifan.com/books/api_tool_postman/website) 16 | 17 | * **优点**: 18 | * 方便 19 | * 因为本身往往已用Postman调试接口,调试完毕后,即可发布 20 | * 及时更新文档 21 | * 同理,在后台代码更新后,用Postman调试无误后,即可再次点击发布即可,无须手动修改API文档 22 | * 美观 23 | * Postman生成的在线的API文档已足够清晰和美观 24 | * **缺点**: 25 | * 必须依赖于在Postman中调试接口 26 | -------------------------------------------------------------------------------- /src/restful_tool/framework_lib.md: -------------------------------------------------------------------------------- 1 | # Restful的API开发设计工具和框架 2 | 3 | ## Python语言 4 | 5 | 在用Python语言去实现服务端的`REST`接口时,常见的框架和库是: 6 | 7 | * [Django](https://www.djangoproject.com) + [DRF](https://www.django-rest-framework.org)=`Django REST Framework` 8 | * [Flask](http://flask.pocoo.org) + [Flask-RESTful](https://github.com/flask-restful/flask-restful) 9 | 10 | ## Javascript 11 | 12 | [NodeJS的ExpressJS](http://expressjs.com) 13 | 14 | ## PHP 15 | 16 | [Slim](https://www.slimframework.com) 17 | 18 | ## Ruby 19 | 20 | [Sinatra](http://www.sinatrarb.com) 21 | 22 | ## .NET 23 | 24 | [Nancy - Lightweight Web Framework for .net](http://nancyfx.org) 25 | -------------------------------------------------------------------------------- /src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # HTTP后台端:RESTful API接口设计 2 | 3 | * [前言](README.md) 4 | * [RESTful API简介](restful_intro/README.md) 5 | * [举例](restful_intro/example.md) 6 | * [RESTful API通用设计规则](restful_rule/README.md) 7 | * [通用设计规则](restful_rule/rule.md) 8 | * [HATEOAS](restful_rule/hateoas.md) 9 | * [RESTful API工具和库](restful_tool/README.md) 10 | * [开发测试工具](restful_tool/test_tool.md) 11 | * [框架和库](restful_tool/framework_lib.md) 12 | * [RESTful API如何写接口文档](restful_doc/README.md) 13 | * [用Markdown写API文档](restful_doc/use_markdown.md) 14 | * [用Postman生成API文档](restful_doc/use_postman.md) 15 | * [用Swagger生成API文档](restful_doc/use_swagger.md) 16 | * [RESTful API心得和经验](restful_experience/README.md) 17 | * [不好的设计风格](restful_experience/bad_design.md) 18 | * [返回数据的格式和风格](restful_experience/resp_data_style.md) 19 | * [分页设计](restful_experience/pagination.md) 20 | * [其他心得](restful_experience/experience_other.md) 21 | * [附录](appendix/README.md) 22 | * [参考资料](appendix/reference.md) 23 | -------------------------------------------------------------------------------- /src/restful_experience/resp_data_style.md: -------------------------------------------------------------------------------- 1 | # RESTful API接口返回数据的格式和风格 2 | 常见返回的数据的格式一般用JSON。 3 | 4 | 对应返回的内容,常见的做法是: 5 | 6 | * `code`:http的status code 7 | * 如果有自己定义的额外的错误,那么也可以考虑用自己定义的错误码 8 | * `message`:对应的文字描述信息 9 | * 如果是出错,则显示具体的错误信息 10 | * 否则操作成功,一般简化处理都是返回OK 11 | * `data` 12 | * 对应数据的json字符串 13 | * 如果是**数组**,则对应最外层是**\[\]**的`list` 14 | * 如果是**对象**,则对应最外层是**\{\}**的`dict` 15 | 16 | 比如之前某项目中设计的返回的数据格式: 17 | 1. code是200 18 | 创建用户 19 | `POST /v1.0/open/register` 20 | 返回: 21 | ````json 22 | { 23 | "code": 200, 24 | "message": "new user has created", 25 | "data": { 26 | "id": "user-4d51faba-97ff-4adf-b256-40d7c9c68103", 27 | "firstName": "crifan", 28 | "lastName": "Li", 29 | "password": "654321", 30 | "phone": "13511112222", 31 | "createdAt": "2016-10-24T20:39:46", 32 | "updatedAt": "2016-10-24T20:39:46" 33 | ...... 34 | } 35 | } 36 | ```` 37 | 38 | 2. code是401 39 | ````json 40 | { 41 | "code": 401, 42 | "message": "invalid access token: wrong or expired" 43 | } 44 | ```` 45 | 46 | -------------------------------------------------------------------------------- /src/restful_intro/README.md: -------------------------------------------------------------------------------- 1 | # RESTful API简介 2 | 3 | 服务器后台设计API接口时,目前最流行的风格(原则/标准/规范)就是`RESTful`,往往简称为`REST`。 4 | 5 | 其中 `REST`=`REpresentational State Transfer` 6 | 7 | * `REST`直译:表现层状态转移 8 | * `REST`核心含义:无状态的资源 9 | * 资源的变化(CURD)都是通过操作去实现的 10 | * 资源可以用 [URI](https://en.wikipedia.org/wiki/Uniform_resource_identifier) 表示 11 | * 用不同的URI和方法,表示对资源的不同操作 12 | * 典型的: 13 | * `GET`:获取资源 14 | * `POST`:新建资源 15 | * `PUT`:更新资源 16 | * `DELETE`:删除资源 17 | 18 | ## `REST`接口设计的特点/要求 19 | 20 | * 接口形式统一=Uniform Interface 21 | * 无状态=Stateless 22 | * 可缓存=Cacheable 23 | * 客户端服务器架构=Client-Server 24 | * 分层设计=Layered System 25 | * [可选]按需执行=COD(Code on Demand) 26 | * 解释见:[What is the code-on-demand constraint? - The RESTful cookbook](http://restcookbook.com/Basics/codeondemand/) 27 | 28 | ## RESTful的通俗理解 29 | 30 | 借用[某人](https://www.zhihu.com/question/28557115/answer/41267240)的总结: 31 | 32 | * 看`url`就知道**要什么** 33 | * 看`http method`就知道**干什么** 34 | * 看`http status code`就知道**结果如何** 35 | 36 | ### 其他类型的接口设计风格\(含RESTful\) 37 | 38 | * `ROA`=`Resource Oriented Architecture` 39 | * `RPC`=`Remote Procedure Call` 40 | * `SOA`=`Simple Object Access Protocol` 41 | * `REST`=`REpresentational State Transfer` 42 | 43 | ### 关于无状态的解释 44 | 45 | #### 有状态 46 | 47 | ![](../assets/img/have_state.png) 48 | 49 | #### 无状态 50 | 51 | ![](../assets/img/stateless.png) 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # HTTP后台端:RESTful API接口设计 2 | 3 | * 最新版本:`v3.0` 4 | * 更新时间:`20190530` 5 | 6 | ## 鸣谢 7 | 8 | 感谢我的老婆**陈雪雪**的包容理解和悉心照料,才使得我`crifan`有更多精力去专注技术专研和整理归纳出这些电子书和技术教程,特此鸣谢。 9 | 10 | ## 简介 11 | 12 | 整理过[HTTP知识总结](http://book.crifan.com/books/http_summary/website)后,继续去整理`HTTP`的**后台**相关的技术。在服务器后台进行设计API接口时,目前最流行的风格(原则/标准/规范)就是`RESTful`,常简称为`REST`接口。 13 | 14 | ## 源码+浏览+下载 15 | 16 | 本书的各种源码、在线浏览地址、多种格式文件下载如下: 17 | 18 | ### Gitbook源码 19 | 20 | * [crifan/http_restful_api: HTTP后台端:RESTful API接口设计](https://github.com/crifan/http_restful_api) 21 | 22 | #### 如何使用此Gitbook源码去生成发布为电子书 23 | 24 | 详见:[crifan/gitbook_template: demo how to use crifan gitbook template and demo](https://github.com/crifan/gitbook_template) 25 | 26 | ### 在线浏览 27 | 28 | * [HTTP后台端:RESTful API接口设计 book.crifan.com](http://book.crifan.com/books/http_restful_api/website) 29 | * [HTTP后台端:RESTful API接口设计 crifan.github.io](https://crifan.github.io/http_restful_api/website) 30 | 31 | ### 离线下载阅读 32 | 33 | * [HTTP后台端:RESTful API接口设计 PDF](http://book.crifan.com/books/http_restful_api/pdf/http_restful_api.pdf) 34 | * [HTTP后台端:RESTful API接口设计 ePub](http://book.crifan.com/books/http_restful_api/epub/http_restful_api.epub) 35 | * [HTTP后台端:RESTful API接口设计 Mobi](http://book.crifan.com/books/http_restful_api/mobi/http_restful_api.mobi) 36 | 37 | ## 版权说明 38 | 39 | 此电子书教程的全部内容,如无特别说明,均为本人原创和整理。其中部分内容参考自网络,均已备注了出处。如有发现侵犯您版权,请通过邮箱联系我 `admin 艾特 crifan.com`,我会尽快删除。谢谢合作。 -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | # HTTP后台端:RESTful API接口设计 2 | 3 | * 最新版本:`v3.0` 4 | * 更新时间:`20190530` 5 | 6 | ## 鸣谢 7 | 8 | 感谢我的老婆**陈雪雪**的包容理解和悉心照料,才使得我`crifan`有更多精力去专注技术专研和整理归纳出这些电子书和技术教程,特此鸣谢。 9 | 10 | ## 简介 11 | 12 | 整理过[HTTP知识总结](http://book.crifan.com/books/http_summary/website)后,继续去整理`HTTP`的**后台**相关的技术。在服务器后台进行设计API接口时,目前最流行的风格(原则/标准/规范)就是`RESTful`,常简称为`REST`接口。 13 | 14 | ## 源码+浏览+下载 15 | 16 | 本书的各种源码、在线浏览地址、多种格式文件下载如下: 17 | 18 | ### Gitbook源码 19 | 20 | * [crifan/http_restful_api: HTTP后台端:RESTful API接口设计](https://github.com/crifan/http_restful_api) 21 | 22 | #### 如何使用此Gitbook源码去生成发布为电子书 23 | 24 | 详见:[crifan/gitbook_template: demo how to use crifan gitbook template and demo](https://github.com/crifan/gitbook_template) 25 | 26 | ### 在线浏览 27 | 28 | * [HTTP后台端:RESTful API接口设计 book.crifan.com](http://book.crifan.com/books/http_restful_api/website) 29 | * [HTTP后台端:RESTful API接口设计 crifan.github.io](https://crifan.github.io/http_restful_api/website) 30 | 31 | ### 离线下载阅读 32 | 33 | * [HTTP后台端:RESTful API接口设计 PDF](http://book.crifan.com/books/http_restful_api/pdf/http_restful_api.pdf) 34 | * [HTTP后台端:RESTful API接口设计 ePub](http://book.crifan.com/books/http_restful_api/epub/http_restful_api.epub) 35 | * [HTTP后台端:RESTful API接口设计 Mobi](http://book.crifan.com/books/http_restful_api/mobi/http_restful_api.mobi) 36 | 37 | ## 版权说明 38 | 39 | 此电子书教程的全部内容,如无特别说明,均为本人原创和整理。其中部分内容参考自网络,均已备注了出处。如有发现侵犯您版权,请通过邮箱联系我 `admin 艾特 crifan.com`,我会尽快删除。谢谢合作。 -------------------------------------------------------------------------------- /src/restful_experience/bad_design.md: -------------------------------------------------------------------------------- 1 | # 不好的API设计风格 2 | 3 | ## 所有的资源的操作类型,都用`POST` 4 | 5 | 听说过,有些偷懒的人,有坏习惯的人,竟然为了省事而去:**把所有的资源的操作类型都用`POST`** 6 | 7 | 而不去管,实际上应该用`GET`、`PUT`、`DELETE`等操作。 8 | 9 | 不论你之前是否有这个坏习惯,都不要继续再有这种坏习惯和坏做法了。 10 | 11 | 而是应该根据资源的内容和操作的目的,分别用对应的`HTTP`的合适的方法:`GET`、`POST`、`PUT`、`DELETE` 12 | 13 | ## 在接口中添加GET/UPDATE等动词 14 | 15 | 比如: 16 | 17 | * `GET /getUser` 18 | * `POST /updateUser` 19 | * `POST /cowfarm/cowfarmemp/new` 20 | * `POST /cowfarm/cowfarmemp/update` 21 | * `POST /cowfarm/cowfarmemp/delete/{id}` 22 | * 且返回值中包含了data和对应的字段 23 | 24 | 实际上不应该在接口中加这些动词,而应该通过接口的HTTP方法,GET/UPDATE,来表示接口的含义,比如改为: 25 | 26 | * `GET /user` 27 | * **获取**一个用户的信息 28 | * `PUT /user` 29 | * **更新**用户的信息 30 | * `POST /cowfarm/employee` 31 | * 表示 **新建** 一个农场的雇员/员工 32 | * `PUT /cowfarm/employee` 33 | * 表示 **更新** 农场雇员/员工的信息 34 | * `DELETE /cowfarm/employee` 35 | * body中包含json参数 36 | * ```{"id": xxx}``` 37 | * 表示 **删除** 用户 38 | * 且返回值中,message,code应该正常返回,data就没必要返回了。 39 | 40 | ## 非改动资源的操作却设计为POST/PUT等方法 41 | 42 | 对于没有新增/更新/删除等去改动和影响资源的操作,HTTP的方法却设计为POST/PUT等 43 | * 很多公司的后台开发人员,为了偷懒省事,所有的接口都用POST,包括本应该用GET的接口 44 | * 或者是,对API接口设计规范不了解,把仅仅是获取、查询资源,不会改动资源的接口设计成POST 45 | 46 | 比如,不好的做法: 47 | * 通过id获取task信息:`POST /task` 48 | * body参数:`{ "id": "1234" }` 49 | * 查询出符合条件的任务:`POST /task/query` 50 | * 参数放在body中 `{"keyword”:”xxx”, “start”: 0, “limit”: 10}` 51 | 应该改为正常的做法: 52 | * `GET /task/{id}` 53 | * 或:`GET /task?id=1234` 54 | * `GET /task/query?keyword=xxxx&start=0&limit=10` 55 | * 其中GET的query string在客户端调用API接口时,往往不是手动加上去 56 | * 而是传递一个字典变量,然后用相关的encode函数去编码出来的 57 | * 详见:[HTTP知识总结](http://book.crifan.com/books/http_summary/website/) 58 | * 这样才能确保参数中包含特殊字符,服务器端也能正常接受,比如: 59 | * 空格 -> `%20` 60 | * 中文"李茂" -> 被UTF-8编码为 -> `%e6%9d%8e%e8%8c%82` 61 | -------------------------------------------------------------------------------- /src/restful_experience/experience_other.md: -------------------------------------------------------------------------------- 1 | # 其他RESTful API心得 2 | 3 | ## 调用api时要有**http**的前缀,否则出错`Error Domain` 4 | 5 | 关于其他(比如移动)端去调用REST的api时,要注意一点的是: 6 | 7 | 记得url地址写全了,最前面要加上`http`或`https`的前缀, 比如: 8 | 9 | `http://115.29.173.126:21084/runningfast/api/v1.0/open/smscode` 10 | 11 | 否则,如果漏了,变成: 12 | 13 | `115.29.173.126:21084/runningfast/api/v1.0/open/smscode` 14 | 15 | 就会报错: 16 | 17 | `FAILURE: Error Domain=NSURLErrorDomain Code=-1002 unsupported URL`或`URL not supported` 18 | 19 | 详见:[【已解决】iOS端用Alamofire访问Flask的rest的api出错:Error Domain=NSURLErrorDomain Code=-1002](http://www.crifan.com/ios_alamofire_http_error_domain_nsurlerrordomain_code_1002) 20 | 21 | ## api中是否一定要加版本号? 22 | 23 | 如果是为了设计长期稳定的API接口,则最好是加上版本号v1.0这种写法 24 | `http://[hostname]/todo/api/v1.0/` 25 | 但是往往中小型项目不需要这么长期维护和不需要迭代太多版本,则可以考虑不需要版本号,则可以写成: 26 | `http://[hostname]/todo/api/` 27 | 即可。 28 | 29 | 另外了解到: 30 | 有些的做法是把API的版本号v1,放到request header中。 31 | ->github就是这么做的:[Media Types | GitHub Developer Guide](https://developer.github.com/v3/media/#request-specific-version) 32 | 33 | ## 设计Restful的接口时,尽量用复数,且统一 34 | 35 | 即,用`/artists`而不要用`/artist` 36 | 37 | ## 如果有多个对象,用模块化逻辑,嵌套资源去设计接口 38 | 39 | 举例: 40 | 41 | 获取某个(内部id为8的)歌手的所有的专辑: 42 | `GET /artists/8/albums` 43 | 44 | ## 是否一定要严格按照Restful的规则,用对应的http的method实现对应的功能? 45 | 46 | 一般来说,不用非常严格的依照规则,尤其是 47 | 48 | * UPDATE/PATCH 去更新修改资源 49 | * 往往为了简化,用PUT表示 更新修改资源即可 50 | 51 | 不过,有些项目,对方本身就要求设计接口时,严格按照Restful的规则来设计,这时最好用UPDATE/PATCH去更新修改资源。 52 | 53 | 其他的,见上面的表格总结,典型的是: 54 | 55 | * `GET` 获取资源 56 | * `POST` 新建资源 57 | * `PUT` 更新/修改 资源 58 | * `DELETE` 删除资源 59 | 60 | ## POST时body中无参数时不应该添加`Content-Type:application/json`的Header 61 | 62 | 比如`POST`时,如果没有Body内容参数传递时,Header中就不要包含 `Content-Type:application/json` 63 | 64 | 否则,某些服务器就会返回错误。 65 | 66 | 比如Flask的Flask-Restful的接口就会自动返回: 67 | 68 | `code = 0 message = Failed to decode JSON object: No JSON object could be decoded` 69 | 70 | -》其意思是,你指定了 71 | 72 | `Content-Type:application/json` 73 | 74 | 所以框架就会去尝试从Body中找JSON字符串,去解析参数 75 | 76 | 但是发现Body是空的,没有可用的JSON字符串待解析,所以报这个错误。 77 | -------------------------------------------------------------------------------- /src/restful_intro/example.md: -------------------------------------------------------------------------------- 1 | # RESTful API常见形式举例 2 | 3 | 下面找些常见的RESTful的API供参考和有个直观的概念: 4 | 5 | ## RESTful的订单的API 6 | 7 | ``` 8 | ========== ===================== ================================== 9 | HTTP 方法 行为 示例 10 | ========== ===================== ================================== 11 | GET 获取资源的信息 http://example.com/api/orders 12 | GET 获取某个特定资源的信息 http://example.com/api/orders/123 13 | POST 创建新资源 http://example.com/api/orders 14 | PUT 更新资源 http://example.com/api/orders/123 15 | DELETE 删除资源 http://example.com/api/orders/123 16 | ========== ====================== ================================== 17 | ``` 18 | 19 | ## RESTful的客户的API 20 | 21 | ``` 22 | POST http://www.example.com/customers 23 | POST http://www.example.com/customers/12345/orders 24 | 25 | GET http://www.example.com/customers/12345 26 | GET http://www.example.com/customers/12345/orders 27 | GET http://www.example.com/buckets/sample 28 | 29 | PUT http://www.example.com/customers/12345 30 | PUT http://www.example.com/customers/12345/orders/98765 31 | PUT http://www.example.com/buckets/secret_stuff 32 | 33 | DELETE http://www.example.com/customers/12345 34 | DELETE http://www.example.com/customers/12345/orders 35 | DELETE http://www.example.com/bucket/sample 36 | ``` 37 | 38 | ## RESTful的待办事项TodoList的API 39 | 40 | ``` 41 | ========== =============================================== ============= 42 | HTTP 方法 URL 动作 43 | ========== =============================================== ============= 44 | GET http://[hostname]/todo/api/v1.0/tasks 检索任务列表 45 | GET http://[hostname]/todo/api/v1.0/tasks/[task_id] 检索某个任务 46 | POST http://[hostname]/todo/api/v1.0/tasks 创建新任务 47 | PUT http://[hostname]/todo/api/v1.0/tasks/[task_id] 更新任务 48 | DELETE http://[hostname]/todo/api/v1.0/tasks/[task_id] 删除任务 49 | ========== ================================================ ============= 50 | ``` 51 | 52 | 更多细节详见:**【整理】TodoList待办事项:常被用于解释一个概念和框架如何应用)** 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/restful_rule/hateoas.md: -------------------------------------------------------------------------------- 1 | # HATEOAS 2 | 3 | `HATEOAS` = `Hypermedia As The Engine Of Application State` = `超媒体即应用状态引擎` 4 | 5 | 谈到`REST`时,往往会提到这个`HATEOAS`。 6 | 7 | ## 什么是`HATEOAS`? 8 | 9 | 或者说: 10 | 11 | * 为何会有`HATEOAS`? 12 | * `HATEOAS`有什么好处或作用? 13 | 14 | 找个例子来比喻,就容易理解了: 15 | 16 | ### 举例解释`HATEOAS` 17 | 18 | 比如有个`用户`的对象,或者说**资源**,定义是: 19 | 20 | ```java 21 | class Customer { 22 | String name; 23 | } 24 | ``` 25 | 26 | 而普通的`REST`,`GET`后返回的信息是: 27 | 28 | ```json 29 | { 30 | "name" : "Alice" 31 | } 32 | ``` 33 | 34 | 而简单点的`HATEOAS`则返回是: 35 | 36 | ```json 37 | { 38 | "name": "Alice", 39 | "links": [ { 40 | "rel": "self", 41 | "href": "http://localhost:8080/customer/1" 42 | } ] 43 | } 44 | ``` 45 | 46 | 好处是: 47 | 48 | 客户端,不需要再去问提供了接口的服务器端,就可以通过此`HATEOAS`返回的信息中知道一些额外的信息: 49 | 50 | * `rel`: 表示`relationship`关系。此处的`self`指的是就是对象`Customer`自己本身。 51 | * 而更加复杂点的情况中,可能会包含其他的对象,比如`"rel":"customer"` 52 | * `href`:当前对象的完整的`url`地址。 53 | 54 | 由此可以看出: 55 | 56 | 如果后台接口支持,或者说实现了`HATEOAS`这套标准(规范),那么: 57 | 58 | 调用接口的前端(移动端等),就可以像: 59 | 60 | 用户通过点击页面的`href`的链接地址,而跳转到其他网页,实现浏览网页的过程了。 61 | 62 | -> 让调用`REST`的api就可以实现,类似于用户浏览网页的从一个页面跳转到另外一个页面的过程了 63 | 64 | -> **而这种超链接方式的api用于告诉用户:该资源的只允许哪些操作(比如`GET`,`POST`),以及不允许哪些操作(比如`DELETE`)** 65 | 66 | -> 从而达到方便用户更加清楚使用你的接口的目的 67 | 68 | ## 其他`HATEOAS`实例 69 | 70 | * [Eve (Python)](https://docs.mongodb.com/ecosystem/tools/http-interfaces/#eve-python) 71 | * [RESTHeart (Java)](https://docs.mongodb.com/ecosystem/tools/http-interfaces/#restheart-java) 72 | 73 | ## 关于`HATEOAS`的最佳实践:**不用`HATEOAS`** 74 | 75 | 但是`HATEOAS`的缺点也很明显: 76 | 77 | 就把简单的返回的信息,搞的更加复杂了。 78 | 79 | 也因此实际在开发`REST`的api过程中,至少我是很少采用这个规范的。 80 | 81 | 当然,也有和我持同样观点的,比如[这位](https://jeffknupp.com/blog/2014/06/03/why-i-hate-hateoas/) 82 | 83 | -》这样会让前端解析API时,倒是变得更加复杂了。显得多此一举和增加复杂度了。 84 | 85 | 而之前自己在折腾[选择好的Flask的REST API的框架](http://www.crifan.com/choose_better_flask_rest_api_framework_lib)期间,本来觉得`eve`不错,后来就是由于发现`eve`默认使用`HATEOAS`,把返回的`json`搞的太复杂,而放弃`eve`的。 86 | 87 | 顺带提及一点的是: 88 | 89 | 针对于`HATEOAS`标准,也还有是别人会用的。 90 | 91 | 所以一些流行的`REST`的框架中,有些也是内置支持了`HATEOAS`。 92 | 93 | 比如:`Flask`的`REST`框架: 94 | 95 | * [eve](https://github.com/pyeve/eve) 96 | * [ripozo](https://github.com/vertical-knowledge/ripozo) 97 | * [flask-marshmallow](https://github.com/marshmallow-code/flask-marshmallow) 98 | 99 | 另外,再贴出来一个复杂点的`HATEOAS`的例子,仅供了解: 100 | 101 | ```json 102 | { 103 | "content": [ { 104 | "price": 499.00, 105 | "description": "Apple tablet device", 106 | "name": "iPad", 107 | "links": [ { 108 | "rel": "self", 109 | "href": "http://localhost:8080/product/1" 110 | } ], 111 | "attributes": { 112 | "connector": "socket" 113 | } 114 | }, { 115 | "price": 49.00, 116 | "description": "Dock for iPhone/iPad", 117 | "name": "Dock", 118 | "links": [ { 119 | "rel": "self", 120 | "href": "http://localhost:8080/product/3" 121 | } ], 122 | "attributes": { 123 | "connector": "plug" 124 | } 125 | } ], 126 | "links": [ { 127 | "rel": "product.search", 128 | "href": "http://localhost:8080/product/search" 129 | } ] 130 | } 131 | ``` 132 | -------------------------------------------------------------------------------- /book.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "总结HTTP后台方面的RESTful API方面的知识", 3 | "links": { 4 | "sidebar": { 5 | "主页": "http://www.crifan.com" 6 | } 7 | }, 8 | "author": "Crifan Li ", 9 | "title": "HTTP后台端:RESTful API接口设计", 10 | "gitbook": "3.2.3", 11 | "language": "zh-hans", 12 | "plugins": [ 13 | "google-adsense", 14 | "theme-comscore", 15 | "anchors", 16 | "-lunr", 17 | "-search", 18 | "search-plus", 19 | "disqus", 20 | "-highlight", 21 | "prism", 22 | "prism-themes", 23 | "github-buttons", 24 | "splitter", 25 | "-sharing", 26 | "sharing-plus", 27 | "tbfed-pagefooter", 28 | "expandable-chapters-small", 29 | "ga", 30 | "donate", 31 | "sitemap-general", 32 | "copy-code-button", 33 | "callouts", 34 | "toolbar-button" 35 | ], 36 | "pluginsConfig": { 37 | "toolbar-button": { 38 | "url": "http://book.crifan.com/books/http_restful_api/pdf/http_restful_api.pdf", 39 | "icon": "fa-file-pdf-o", 40 | "label": "下载PDF" 41 | }, 42 | "sitemap-general": { 43 | "prefix": "https://book.crifan.com/gitbook/http_restful_api/website/" 44 | }, 45 | "sharing": { 46 | "qq": true, 47 | "douban": false, 48 | "all": [ 49 | "douban", 50 | "facebook", 51 | "google", 52 | "instapaper", 53 | "line", 54 | "linkedin", 55 | "messenger", 56 | "pocket", 57 | "qq", 58 | "qzone", 59 | "stumbleupon", 60 | "twitter", 61 | "viber", 62 | "vk", 63 | "weibo", 64 | "whatsapp" 65 | ], 66 | "google": false, 67 | "stumbleupon": false, 68 | "hatenaBookmark": false, 69 | "twitter": true, 70 | "vk": false, 71 | "linkedin": false, 72 | "instapaper": false, 73 | "pocket": false, 74 | "weibo": true, 75 | "viber": false, 76 | "facebook": true, 77 | "qzone": false, 78 | "messenger": false, 79 | "line": false, 80 | "whatsapp": false 81 | }, 82 | "tbfed-pagefooter": { 83 | "modify_format": "YYYY-MM-DD HH:mm:ss", 84 | "modify_label": "最后更新:", 85 | "copyright": "crifan.com,使用署名4.0国际(CC BY 4.0)协议发布" 86 | }, 87 | "github-buttons": { 88 | "buttons": [ 89 | { 90 | "repo": "http_restful_api", 91 | "count": true, 92 | "type": "star", 93 | "user": "crifan", 94 | "size": "small" 95 | }, 96 | { 97 | "count": false, 98 | "width": "120", 99 | "type": "follow", 100 | "user": "crifan", 101 | "size": "small" 102 | } 103 | ] 104 | }, 105 | "disqus": { 106 | "shortName": "crifan" 107 | }, 108 | "prism": { 109 | "css": [ 110 | "prism-themes/themes/prism-atom-dark.css" 111 | ] 112 | }, 113 | "donate": { 114 | "alipay": "https://www.crifan.com/files/res/crifan_com/crifan_alipay_pay.jpg", 115 | "title": "", 116 | "alipayText": "支付宝打赏给Crifan", 117 | "button": "打赏", 118 | "wechatText": "微信打赏给Crifan", 119 | "wechat": "https://www.crifan.com/files/res/crifan_com/crifan_wechat_pay.jpg" 120 | }, 121 | "ga": { 122 | "token": "UA-28297199-1" 123 | }, 124 | "theme-default": { 125 | "showLevel": true 126 | }, 127 | "google-adsense": { 128 | "ads": [ 129 | { 130 | "slot": "6956288491", 131 | "client": "ca-pub-6626240105039250", 132 | "location": ".page-inner section", 133 | "format": "auto" 134 | } 135 | ] 136 | }, 137 | "callouts": { 138 | "showTypeInHeader": false 139 | } 140 | }, 141 | "root": "./src" 142 | } -------------------------------------------------------------------------------- /src/restful_doc/use_markdown.md: -------------------------------------------------------------------------------- 1 | # 用Markdown写API文档 2 | 举例: 3 | 一个GET方法,用于获取验证码的接口: 4 | 在postman中已经调试完毕: 5 | 6 | ![](../assets/img/postman_debug_api.png) 7 | 然后去(推荐)有道云笔记中编写markdown: 8 | 9 | ````markdown 10 | # API接口 11 | 12 | ## 注册 13 | 14 | ### 获取验证码 15 | 16 | 目前有4种短信验证码,对应的type是: 17 | - 注册短信验证码: register 18 | - 修改密码短信验证码: changePassword 19 | - 修改手机短信验证码: changePhoneNumber 20 | - 验证手机号短信验证码: verifyPhoneNumber 21 | #### Request 22 | - Method: **GET** 23 | - URL: ```/v1.0/open/smscode?type={type}&phone={phone}``` 24 | - register for new user: ```/v1.0/open/smscode?type=register&phone=13811119999``` 25 | - forgot password: ```/v1.0/open/smscode?type=changePassword&phone=13822224444``` 26 | - Headers: 27 | - Body: 28 | ``` 29 | ``` 30 | 31 | #### Response 32 | - Body 33 | ``` 34 | { 35 | "code": 200, 36 | "data": "730781", 37 | "message": "OK" 38 | } 39 | ``` 40 | 41 | 注意:为了防止短信验证码被滥用,短信如果发送后,需要隔60s才能重新发送。 42 | ```` 43 | 44 | 对应的效果: 45 | ![](../assets/img/youdao_markdown_preview_1.png) 46 | ![](../assets/img/youdao_markdown_preview_2.png) 47 | 48 | 另外,再举个有request也有response的POST的例子: 49 | 50 | ````markdown 51 | ### 创建新用户 52 | #### Reuqest 53 | 54 | - Method: **POST** 55 | - URL: ```/v1.0/open/register``` 56 | - Headers: Content-Type:application/json 57 | - Body: 58 | ``` 59 | { 60 | "phone" : "13511112222", 61 | "smsCode" : "730781", 62 | "email" : "crifan@webonn.com", 63 | "firstName" : "crifan", 64 | "lastName" : "Li", 65 | "password" : "654321", 66 | "facebookUserId" : "123907074803456" 67 | } 68 | ``` 69 | 70 | #### Response 71 | - Body 72 | ``` 73 | { 74 | "code": 200, 75 | "data": { 76 | "avatarUrl": "", 77 | "createdAt": "2016-10-24T20:39:46", 78 | "curRole": "IdleNoRole", 79 | "email": "crifan@webonn.com", 80 | "errandorRating": 0, 81 | "facebookUserId": "123907074803456", 82 | "firstName": "crifan", 83 | "id": "user-4d51faba-97ff-4adf-b256-40d7c9c68103", 84 | "isOnline": false, 85 | "lastName": "Li", 86 | "location": { 87 | "createdAt": null, 88 | "fullStr": null, 89 | "id": null, 90 | "latitude": null, 91 | "longitude": null, 92 | "shortStr": null, 93 | "updatedAt": null 94 | }, 95 | "locationId": null, 96 | "password": "654321", 97 | "phone": "13511112222", 98 | "shareCodeCount": 0, 99 | "updatedAt": "2016-10-24T20:39:46" 100 | }, 101 | "message": "new user has created" 102 | } 103 | ``` 104 | ```` 105 | 106 | markdown生成文档的效果: 107 | 108 | ![](../assets/img/create_new_md_preview_1.png) 109 | 110 | ![](../assets/img/create_new_md_preview_2.png) 111 | 112 | 所以后续其他接口,均可参考上面的GET/POST等接口的写法,去写出对应的markdown的源文件,生成API文档后,效果还是不错的。 113 | 114 | 当然,也可以用其他Markdown编辑器去写md文件,去生成对应API文档。 115 | 116 | 另外,再附上,在写具体单个API接口之前的声明的部分: 117 | ````markdown 118 | # 文档说明 119 | ## 服务器API地址 120 | 前缀: 121 | ```http://115.29.173.126:21084/runningfast/api``` 122 | 123 | 124 | 完整的API地址为:```前缀```+```具体接口路径``` 125 | 126 | 比如,获取验证码都接口为: 127 | ```http://115.29.173.126:21084/runningfast/api``` + ```/v1.0/open/smscode``` 128 | 129 | -> 130 | 131 | ```http://115.29.173.126:21084/runningfast/api/v1.0/open/smscode``` 132 | 133 | ## 调用接口说明 134 | - 如果参数格式是==JSON==的话:提交request请求时必须添加header头:==Content-Type:application/json== 135 | - 请求中是否要包含头信息:==Authorization:{accesstoken}== 136 | - 接口中==包含==```/open/```的:不需要添加 137 | - 接口中==不包含==```/open/```:需要添加 138 | - 说明该接口都需要对应的权限才可以访问,所以需要在请求中包含头信息:```Authorization:{accesstoken}``` 139 | - 当access token无效或者已过期时,返回: 140 | ``` 141 | { 142 | "code": 401, 143 | "message": "invalid access token: wrong or expired" 144 | } 145 | ``` 146 | 147 | - 所有的接口的返回形式都是统一为: 148 | - 正常返回 149 | ``` 150 | { 151 | "code": 200, 152 | "message": "OK", 153 | "data": 某种类型的数据,比如字符串,数字,字典等等 154 | } 155 | ``` 156 | - 错误返回 157 | 158 | ``` 159 | { 160 | "code": 具体的错误码, 161 | "message": "具体的错误信息字符串" 162 | } 163 | ``` 164 | ```` 165 | 文档效果: 166 | 167 | ![](../assets/img/youdao_markdown_explain_preview_1.png) 168 | ![](../assets/img/youdao_markdown_explain_preview_2.png) 169 | 170 | * 优点:简单易上手 171 | * 缺点:后续API更新后,需要及时更新markdown的文档内容 172 | 173 | -------------------------------------------------------------------------------- /src/restful_rule/rule.md: -------------------------------------------------------------------------------- 1 | # 通用设计规则 2 | 3 | 资源:往往对应着后台系统中对象,比如一个用户User,一个待办事项todo item,一个任务Task等等 4 | 5 | 用对应的接口表示要对资源进行何种操作,想要实现什么目的: 6 | 7 | | HTTP Verb=HTTP Method=HTTP方法 | 操作类型=CRUD | 可能返回的状态码 | 是否幂等Idempotent | 是否安全Safe | 8 | | :--- | :--- | :--- | :--- | :--- | 9 | | OPTIONS | 询问该接口/端点支持哪些方法 | 200 OK | 是 | 是 | 10 | | POST | Create创建 |