RESTful Service API 常见问题解决方案
REST 风格的优秀设计应该像下面这些:
如果要设计一个资源拥有另外一个资源的情况的API,例如,设计一个包含用户(users)和用户的评论(comments)的 API 可以采用这样的形式:
- 将这些操作变成一个资源的属性,比如 disable 一个 user,可以在 user 里面加一个 disabled 的属性,可以设计一个 API 使用
PATCH /users/1234
将 disabled 设置成 true 即可。 - 将这个操作看成某个资源的附属资源(就像上面例子中的 comments 一样)来设计,比如GitHub的Star a gist API ,就是这样的,它把star操作放在这个资源的后面,看上去好像是一个附属资源:
- PUT /gists/:id/star
- DELETE /gists/:id/star
在不得不使用其它例外形式设计 API 时,尽量用文档写清楚输入输出和返回值等其他必要信息,避免让习惯了使用资源名的调用者感到困惑
- 比如你要设计一个API,返回所有已经登录的用户,可以这样做:GET /users?login=true
- 获取所有的用户,返回结果按照create_at降序排序可以这样设计:GET /users?sort=-create_at
- 组合使用过滤条件和排序,GET /users?sort=-create_at,login_at&login=true 表示返回所有已登录用户,结果按照create_at降序, login_at升序
- 单独为 API 设计一个 Query Parameter 专门用于搜索,从 API 中传递过来的 Query Parameter 可以直接设置成这些搜索框架的输入条件GET /users?q=key&&sort=-create_at,login_at&diabled=false
- 映射到一个新的API(相当于快捷方式)比如设计一个用于返回最近登录用户的API:GET /users/recently_login这种设计可以简化客户端的调用,否则调用者每次都要根据时间合成 Query Parameter,增加了客户端使用复杂度
- 查询数据的部分内容GET /user?fields=id,user_name,address&diabled=false&sort=-login_at GET /facebook/v2.8/me?fields=id,name,birthday,cover,devices,email&access_token=xxX
API中都使用了下划线(user_name)的形式来命名这些参数,使用划线(user_name)还是使用驼峰(userName)的形式?下划线分割的形式比使用驼峰的形式更容易阅读(容易20%)
合理设计返回数据的形式,格式和考虑启用压缩(gzip)
假如有个系统提供一个 API 用于上传一张图,这张图上传之后你可以调用另外一个 API 修改这个图片的描述。如果调用上传 API 后,返回数据中没有返回这张图的唯一性 ID,你就无法接着调用其它 API 引用到这个图的资源,从而无法进行修改描述的操作,除非之前额外再次调用查询操作拉取到这张图唯一性 ID。
通常,POST 操作成功以后,我们一般也把新创建的资源的 URL 放在 HTTP header 的 location 字段中,方便客户的拉取。例如上上树图片上传的 API 返回的 header 中可以包含location: http://api.domain.name/photos/1234
RESTful API 一般都是返回文本数据,启用 gzip 通常可以节省60%-80%以上的带宽(这个数据很好证明,随便使用几个个 json 文件 gzip下就可以看出来,我测试几个 json 文件一般300K左右都能被压缩成50K左右),尤其是在返回的数据比较大情况下,压缩比更高。不过启用gzip 不可避免会增加 CPU 的负担,实际工程项目中需要权衡考量。
至于到底用什么用的格式来返回数据?XML?JSON?纯文本?但从统计数据来看 JSON 格式目前是使用做多的 REST API 的输入输出格式。
根据不同的 API 操作,设置合适的 HTTP 状态码和必要的出错信息
- 200 OK 用于返回 GET, PUT, PATCH 或 DELETE 的操作。有使用也用来返回没有创建数据的 POST 操作;
- ** 201 Created** 用来返回 POST 操作并且成功创建了数据的情况。新创建的数据资源的链接应该放在location中返回;
- 204 No Content 用来返回一次成功的请求,但是该请求返回的 body 为空的情况,如 DELETE 请求;
- 304 Not Modified 表示缓存没有失效,和上次的请求相比,没有新的内容;
- 400 Bad Request 用于返回 API 参数不正确的情况,比如传入的 JSON 格式错误无法解析等;
- 401 Unauthorized 用于表示请求等 API 缺少身份验证信息;
- 403 Forbidden 用于表示该资源不允许特定用户访问;
- 404 Not Found 请求一个不存在的资源;
- 429 Too Many Requests 请求过于频繁,可以用在客户端调用过于频繁的情况。
使用 token 机制设计鉴权和验证系统(Authorization and Authentication)
常见的场景就是用户系统-结合 OAuth2,参考腾讯云微视频MVS API,这里给出一个实用的解决方案:
- 用户使用户名密码或者第三方登录,最终请求一个我们设计的登录 API(这个 API 接受用户名密码,或第三方登录验证结果);
- 服务端认证成功以后,生成一个 token,并将这个 token 和用户信息关联在一起,同时返回这个 token 给调用客户端;
- 客户端记录并保存下这个 token;
- 下次客户端发起和用户相关请求 API 都要在 http header 中带上这个 token;
- 服务端通过这个 token 去区分用户是谁,判断这个用户是否已经登录和有什么样的权限;
- 服务端也要考虑 token 的失效时间;
- 客户端在发现 token 失效的时候重新请求新的 token
如何实现数据的分页返回
另一种符合WEB标准的做法是使用 link header,简单来说就是在 http header 使用 link字段,提供一个和超链接一样目的 URL 地址,来实现不同资源之间的转跳。如GitHub的Api文档是这样规定分页信息的,这种做法缺点是不太直观,优点是不会干扰数据,返回内容都是数据本身,无需在数据上嵌入额外的属性来说明分页信息,简单干净
如何处理有关联资源的返回数据
对客户端来说,最直观和容易处理的返回形式如下:
返回数据中 avatar 和 name 是每条数据都是重复的,所以你也可以这样设计返回数据:先返回该用户的所有评论 /comments?user=1234
再通过请求该用户 API 的相关内容 /users/1234:{user_id: "1234", avatar: "a.jpg", nickName:"Jeffrey"...}这种情况下其实可以将依赖资源嵌入返回对象中,避免了客户端需要再一次发起请求来获取这个 user 的详细信息/comments?user=1234 直接返回类似这样的信息即可:
考虑启用 HTTP 缓存机制
HTTP协议本身支持两种缓存机制: ETag 和 Last-Modified
- ETag:HTTP 请求中在 header 中包含一个内容的 hash,如果返回结果没有变化,该请求会直接返回304 Not Modified,而不是所有数据内容本身
- Last-Modified: 和 Etag 工作原理差不多,只是使用时间戳作为内容是否过期的标志。
限制 API 调用频次(Rate limiting)
如果一个客户端请求 API 的频率太快,根据HTTP协议,可以返回429 Too Many Requests。
X-Rate-Limit-Limit: 该请求的调用上限
X-Rate-Limit-Remaining: 15分钟内还可以调用多少次
X-Rate-Limit-Reset: 还有多少秒之后访问限制会被重置
HTTPS 现在已经是各种网络服务的标配(比如 Xcode 默认不允许请求不安全的 HTTP 信息)
- ssl_prefer_server_ciphers: 表示服务端加密算法优先于客户端加密算法,主要是防止降级攻击 (downgrade attack)。
- Strict-Transport-Security(HSTS):告诉浏览器这个域名在指定的时间(max-age)内应该强制使用 HTTPS 访问。
RESTful Service API 常见问题解决方案的更多相关文章
- HTTP Methods 和 RESTful Service API 设计
含义: HTTP Methods:也叫 HTTP Verbs,HTTP Methods 可以翻译成 HTTP 方法.它们是 HTTP 协议的一部分,主要规定了 HTTP 如何请求和操作服务器上的资源, ...
- gRPC helloworld service, RESTful JSON API gateway and swagger UI
概述 本篇博文完整讲述了如果通过 protocol buffers 定义并启动一个 gRPC 服务,然后在 gRPC 服务上提供一个 RESTful JSON API 的反向代理 gateway,最后 ...
- 在IIS8.5的环境下配置WCF的Restful Service
今天在客户的环境中(Windows Server 2012 R2 + IIS 8.5)搭建Call WCF Restful Service的功能,发现了几个环境配置的问题,记录如下: 1):此环境先安 ...
- JAVA格物致知基础篇:用JAX-RS和Jersey打造RESTful Service
随着服务器的处理能力越来越强,业务需求量的不断累积,越来越多的公司开始从单一服务器,单一业务承载变成了多服务器,多业务承载的快速扩展的过程中.传统的方法很难满足和应付这种业务量的增长和部署方式的改变. ...
- 构建基于WCF Restful Service的服务
前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添加服务端引用才能使用(虽然看到网络上已经提供了这方面的Dynamic Proxy,但是没有这种方式简便), ...
- 基于.Net FrameWork的 RestFul Service
关于本文 这篇文章的目的就是向大家阐述如何在.net framework 4.0中创建RestFul Service并且使用它. 什么是web Services,什么是WCF 首先讲到的是web Se ...
- spring boot之使用springfox swagger展示restful的api doc
摘要 springfox swagger展示restful的api doc, swagger is A POWERFUL INTERFACE TO YOUR API. 新增文件: import org ...
- WCF Restful Service的服务
构建基于WCF Restful Service的服务 前言 传统的Asmx服务,由于遵循SOAP协议,所以返回内容以xml方式组织.并且客户端需要添加服务端引用才能使用(虽然看到网络上已经提供了这方面 ...
- WCF Restful Service Get / Post请求
Rest 它是用于创建分布式超文本媒体的一种架构方式,我们可以通过标准的HTTP(GET,POST,PUT,DELETE)操作来构建基于面向资源的软件架构方式(Resource-Oriented Ar ...
随机推荐
- Centos7 JDK安装过程中 解决java -version 报错: bash: /home/jdk1.8.0_161/bin/java: Permission denied
1.执行Linux命令 -----vim /etc/profile 编辑profile 文件,在里面添加: #set java enviroment JAVA_HOME=/opt/JavaHome ...
- Sorting Algorithms
Merge sort by using recursive strategy, i.e. divide and conquer. def merge(left,right): result = [] ...
- shiro权限管理的框架-入门
shiro权限管理的框架 1.权限管理的概念 基本上涉及到用户参与的系统都要进行权限管理,权限管理属于系统安全的范畴,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能 ...
- java中super和this的使用
要说super就先要说this."this",作为一个特殊的关键字,它的规则如下: 1.可以表示构造函数传递.this(a,b)表示调用另外一个构造函数.这里面的this就是一个特 ...
- 33 个 2017 年必须了解的 iOS 开源库
本文翻译自Medium,原作者为Pawe? Bia?ecki 照片版权:(Unsplash/Markus Pe) 你好,iOS 开发者们!我的名字叫 Pawe?,我是一个独立 iOS 开发者,并且是 ...
- SQL SERVER版本补丁体系及升级
首先了解几个定义: RTM : 表示 Release to Manufacturing ,这是产品的原始发布版本,当从光盘或 MSDN 下载的默认版本.不过现在下载 SQL Server 版本时,也有 ...
- nyoj 1091 还是01背包(超大数dp)
nyoj 1091 还是01背包 描述 有n个重量和价值分别为 wi 和 vi 的物品,从这些物品中挑选总重量不超过W的物品,求所有挑选方案中价值总和的最大值 1 <= n <=40 1 ...
- 【配置】pom.xml的配置
pom.xml的配置: 地址:https://mvnrepository.com/ 示例:配置log4j 1.在搜索框中搜索log4j 2.在搜索结果页点击log4j 3.选择一个最新的版本,点击 4 ...
- django 中下载文件与下载保存为excel
一.django 中下载文件 在实际的项目中很多时候需要用到下载功能,如导excel.pdf或者文件下载,当然你可以使用web服务自己搭建可以用于下载的资源服务器,如nginx,这里我们主要介绍dja ...
- Angular4-配置
基于 Angular Quickstart git clone https://github.com/angular/quickstart ng4-quickstart npm i npm start ...