在项目中,需要为后台服务撰写API。刚开始接触的时候,并没有考虑太多,就想提供URL,服务端通过该URL进行查询、创建、更新等操作即可。但再对相关规范进行了解后,才发现,API的设计并没有那么简单,远远不是URL的问题,而是一个通信协议的整体架构

1. 使用GET、POST、PUT、DELETE这几种请求模式

请求模式也可以说是动作、数据传输方式,通常我们在web中的form有GET、POST两种,而在HTTP中,存在下发这几种。

GET (选择):从服务器上获取一个具体的资源或者一个资源列表。 

POST (创建): 在服务器上创建一个新的资源。

PUT(更新):以整体的方式更新服务器上的一个资源。 

PATCH (更新):只更新服务器上一个资源的一个属性。

DELETE(删除):删除服务器上的一个资源。

1.1 使用名词而不是动词

Resource
资源

GET
POST
创建
PUT
修改
DELETE
/cars 返回 cars集合 创建新的资源 批量更新cars 删除所有cars
/cars/711 返回特定的car 该方法不允许(405) 更新一个指定的资源 擅长指定资源

不要使用:

/getAllCars
/createNewCar
/deleteAllRedCars

1.2 Get方法和查询参数不应该涉及状态改变

使用PUT, POST 和DELETE 方法 而不是 GET 方法来改变状态,不要使用GET 进行状态改变:

GET /users/711?activate 
GET /users/711/activate

1.3 使用复数名词

不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。

/cars 而不是 /car
/users 而不是 /user
/products 而不是 /product
/settings 而部署 /setting

1.4 使用子资源表达关系

如果一个资源与另外一个资源有关系,使用子资源:

GET /cars/711/drivers/ 返回 car 711的所有司机
GET /cars/711/drivers/4 返回 car 711的4号司机

2. 为集合提供过滤 排序 选择和分页等功能

比如在数据过多, 需要对数据进行分页请求的时候, 我们应该统一 API 请求参数. 常见的有这些.

  • limit=10 指定返回记录的数量
  • offset=10 指定返回记录的开始位置。
  • page=2&per_page=100 指定第几页,以及每页的记录数。
  • sortby=name&order=asc 指定返回结果按照哪个属性排序,以及排序顺序。
  • animal_type_id=1 指定筛选条件

Filtering过滤:

使用唯一的查询参数进行过滤:

GET /cars?color=red 返回红色的cars
GET /cars?seats<=2 返回小于两座位的cars集合

Sorting排序:

允许针对多个字段排序

GET /cars?sort=-manufactorer,+model

这是返回根据生产者降序和模型升序排列的car集合

Field selection

移动端能够显示其中一些字段,它们其实不需要一个资源的所有字段,给API消费者一个选择字段的能力,这会降低网络流量,提高API可用性。

GET /cars?fields=manufacturer,model,id,color

Paging分页

使用 limit 和offset.实现分页,缺省limit=20 和offset=0;

GET /cars?offset=10&limit=5

为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.

链接到下一页或上一页可以在HTTP头的link规定,遵循Link规定:

Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",

3. 版本化你的API

API的开发直接关系了APP是否可以正常使用,如果原本运行正常的API,突然改动,那么之前使用这个API的APP可能无法正常运行。APP是不可能强迫用户主动升级的,因此,通过API版本来解决这个问题。也就是说,API的多个版本是同时运行的,而且都要保证可以正常使用。

按照RESTful的规范,不同的版本也应该用相同的API URL,通过header信息来判断版本,再调用不同版本的程序进行处理。但是这明显会给开发带来巨大的成本。使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5.

域名

应该尽量将API部署在专用域名之下,如:https://api.example.com

也可以放在主域名下:https://example.org/api/

版本

不同的版本,用不同的URL来提供服务,在URL中通过v1、v2来区分版本号,比如v2.api.xxx.com/user的方式,或者http://api.domain.com/v2  或者http://www.domain.com/api/v2 。

放入到头信息的Accept中
制定版本并在版本之间平缓过渡对于设计和维护一套API是个巨大的挑战。所以,最好在设计之初就使用一些方法来预防可能会遇到的问题。
为了避免API的变动导致用户使用中产生意外结果或调用失败,最好强制要求所有访问都需要指定版本号。请避免提供默认版本号,一旦提供,日后想要修改它会相当困难。
最适合放置版本号的位置URL中,或者是头信息(HTTP Headers)中在 Accept 段中使用自定义类型(content type)与其他元数据(metadata)一起提交。

https://api.example.com/v1/

Accept: application/vnd.heroku+json; version=3

提供 Request-Id

为每一个请求响应包含一个Request-Id字段,并使用UUID作为该值。通过在客户端、服务器或任何支持服务上记录该值,它能主我们提供一种机制来跟踪、诊断和调试请求。

4 .json数据类型

  • Number:整数或浮点数
  • String:字符串
  • Boolean:true 或 false
  • Array:数组包含在方括号[]中
  • Object:对象包含在大括号{}中
  • Null:空类型

所以,传输的数据类型不能超过这六种数据类型。以前,我们曾经试过传输Date类型,它会转为类似于"2016年1月7日 09时17分42秒 GMT+08:00"这样的字符串,这在转换时会产生问题,不同的解析库解析方式可能不同,有的可能会转乱,有的可能直接异常了。要避免出错,必须做特殊处理,自己手动去做解析。为了根除这种问题,最好的解决方案是用毫秒数或者字符串表示日期。

使用详细的错误包装错误:

{

  "errors": [

   {

    "userMessage": "Sorry, the requested resource does not exist",

    "internalMessage": "No car found in the database",

    "code": 34,

    "more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"

   }

  ]

}

返回的数据结构

{
code:0,
message: "success",
data: { key1: value1, key2: value2, ... }
}
  • code: 返回码,0表示成功,非0表示各种不同的错误
  • message: 描述信息,成功时为"success",错误时则是错误信息
  • data: 成功时返回的数据,类型为对象或数组

data字段只在请求成功时才会有数据返回的。数据类型限定为对象或数组,当请求需要的数据为单个对象时则传回对象,当请求需要的数据是列表时,则为某个对象的数组。这里需要注意的就是,不要将data传入字符串或数字,即使请求需要的数据只有一个,比如token,那返回的data应该为:

// 正确 data: { token: abcdedf }

9. 使用Http状态码处理错误

不同错误需要定义不同的返回码,属于客户端的错误和服务端的错误也要区分,比如1XX表示客户端的错误,2XX表示服务端的错误

如果你的API没有错误处理是很难的,只是返回500和出错堆栈不一定有用

Http状态码提供70个出错,我们只要使用10个左右:

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

10.允许覆盖http方法

一些代理只支持POST 和 GET方法, 为了使用这些有限方法支持RESTful API,需要一种办法覆盖http原来的方法。

使用订制的HTTP头 X-HTTP-Method-Override 来覆盖POST 方法.

参考:

  1. https://segmentfault.com/a/1190000008697972#articleHeader3
  2. http://blog.csdn.net/jasonhui512/article/details/53141390
  3. http://www.cnblogs.com/kuyuecs/p/5949075.html
  4. http://mclspace.com/2015/11/03/restful-note/

Restful API 设计参考原则的更多相关文章

  1. RESTful API设计原则与规范

    RESTful API设计原则与规范 一.背景与基础概念 2 二.RESTful API应遵循的原则 3 1.协议(Protocol) 3 2.域名(ROOT URL) 3 3.版本(Versioni ...

  2. RESTful API设计概要

    一.简介 1. 什么是REST REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征)性状态转移. 它首次出现在2000年Roy Fiel ...

  3. RESTful API 设计指南 (转)

    RESTful API 设计指南 2016-02-23 ImportNew (点击上方公号,可快速关注) 作者:阮一峰 链接:http://www.ruanyifeng.com/blog/2014/0 ...

  4. RESTFul API设计指南及使用说明

    RESTFul API设计指南及使用说明 一. 协议 API与用户的通信协议,使用HTTP协议. 二. 域名 应尽量将API部署在专用域名之下(http://api.example.com) 也可以将 ...

  5. RESTful API 设计指南,RESTful API 设计最佳实践

    RESTful API 设计指南,RESTful API 设计最佳实践 网络应用程序,分为前端和后端两个部分.当前的发展趋势,就是前端设备层出不穷(手机.平板.桌面电脑.其他专用设备......). ...

  6. 我是如何根据豆瓣api来理解Restful API设计的

    1.什么是REST REST全称是Representational State Transfer,表述状态转移的意思.它是在Roy Fielding博士论文首次提出.REST本身没有创造新的技术.组件 ...

  7. 微服务指南走北(三):Restful API 设计简述

    API的定义取决于选择的IPC通信方式,假设是消息机制(如 AMQP 或者 STOMP).API则由消息频道(channel)和消息类型.假设是使用HTTP机制,则是基于请求/响应(调用http的ur ...

  8. RESTful API 设计总结

    RESTful API 设计总结 @(技术-架构)[API, 规范, 设计] RESTful的接口设计风格应用的越来越广泛,包括Spring Cloud等微服务架构平台之间的调用都是以RESTful设 ...

  9. RESTful API设计的点

    RESTful API 前言 一直在使用RESTful API,但是好像概念还是很模糊的,总结下使用到的点 设计的规范 协议 API与用户的通信协议,总是使用HTTPs协议. 域名 应该尽量将API部 ...

随机推荐

  1. android TextView 设置部分文字背景色和文字颜色

    通过SpannableStringBuilder来实现,它就像html里边的元素改变指定文字的文字颜色或背景色 public class MainActivity extends Activity { ...

  2. 用delegate实现.NET应用程序的同步函数的异步调用-.NET多线程编程实践之一

    在C++中有2种类型的线程:UI Thread和Worker Thread,前者是基于用户界面的有消息循环的线程.后者是没有用户界面的侧重于大时空运算的线程.直接调用Windows相关线程及同步对象的 ...

  3. debian7(wheezy)升级安装mercurial hg最新版2.8-RC,解决tortoisehg2.9.2不能使用。

    debian&(wheezy)之前的仓库版本是2.2.2.  注: 本文以 # 为开始的行是工作在root下的模式,在终端显示为root的提示符# ,用户目录的($:)需要切换到root(使用 ...

  4. 分形之科赫(Koch)雪花

    科赫曲线是一种分形.其形态似雪花,又称科赫雪花.雪花曲线.瑞典人科赫于1904年提出了著名的“雪花”曲线,这种曲线的作法是,从一个正三角形开始,把每条边分成三等份,然后以各边的中间长度为底边.分别向外 ...

  5. jacoco初探

    # 背景 集团的代码覆盖率平台因为网络问题无法使用,只能自己研究下. 覆盖率是衡量自动化用例效果产品的一个指标,但只是一个辅助指标,覆盖率高并不意味着质量好,但覆盖率低却能说明一些问题, # 对比 覆 ...

  6. ASP.NET SignalR Troubeshooting

    method could not be resolved 场景: Javascript客户端不生成代理,调用服务端方法. 按照官网文档的用法: contosoChatHubProxy.invoke(' ...

  7. [leetcode.com]算法题目 - Maximum Subarray

    Find the contiguous subarray within an array (containing at least one number) which has the largest ...

  8. VMware中安装Contos

    1 检查BIOS虚拟化支持 2 新建虚拟机 3 新建虚拟机向导 4 创建虚拟空白光盘 5 安装Linux系统对应的CentOS版 6 虚拟机命名和定位磁盘位置 7 处理器配置,看自己是否是双核.多核 ...

  9. Git-根据tag创建分支

    有时候需要根据tag创建分支. 现在主分支上有一个tag为vtest.1.0.FINAL,主分支的名字为master. 1.执行:git origin fetch 获得最新. 2.通过:git bra ...

  10. svn重新安装后报You need to upgrade the working copy first错误

    问题来源 最近重新安装了操作系统,安装了一个最新版的svn,提交代码的时候报了一个错误:You need to upgrade the working copy first,!网上找了很多解决办法,都 ...