RESTful API的十个最佳实践1. 使用名词而不是动词 2. Get方法和查询参数不应该改变资源状态3. 使用名词的复数形式 4. 为关系使用子资源 5. 使用HTTP头决定序列化格式 6. 使

WebAPI在过去几年里非常的盛行,我们很多以往的技术手段都慢慢的转换为使用WebAPI来开发,因为它的语法简单规范化,以及轻量级等特点,这种方式收到了广泛的推崇。

通常我们使用RESTFul(Representational State Transfer)的设计方式来设计Web api,这通常用来分离API结构了业务逻辑,它使用典型的HTTP方法,诸如GET,POST.DELETE,PUT来和资源进行交互。

以下是设计RESTful API的是个最佳实践:

1. 使用名词而不是动词

为了易于理解,为资源使用下面的API结构:

Resource

Getread

Postcreate

Putupdate

Delete

/cars

返回一个car的列表

创建一个新的car

更新car的信息

删除所有的car

/cars/2

返回指定的car

Method not allowed(405)

更新指定的car的信息

删除指定的car

不要使用动词

/getAllCars
/createNewCar
/deleteAllRedCars

2. Get方法和查询参数不应该改变资源状态

使用Put,Post和Delete方法替代Get方法来改变资源状态。不要使用Get来使状态改变:

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

3. 使用名词的复数形式

不要混合使用单数和复数形式,而应该为所有资源一直保持使用复数形式:

/cars instead of /car
/users instead of /user
/products instead of /product
/settings instead of /setting

4. 为关系使用子资源

假如资源连接到其它资源,则使用子资源形式:

GET /cars/711/drivers/ Returns a list of drivers for car 711
GET /cars/711/drivers/4 Returns driver #4 for car 711

5. 使用HTTP头决定序列化格式

在客户端和服务端都需要知道使用什么格式来进行通信,这个格式应该在HTTP头中指定:

  • Content-Type:定义请求的格式;
  • Accept :定义允许的响应格式的列表

6. 使用HATEOAS

Hypermedia as the Engine of Application State是一个指导原则,它规定超文本链接应该被用于在API中创建更好的资源导航:

{
  "id": 711,
  "manufacturer": "bmw",
  "model": "X5",
  "seats": 5,
  "drivers": [
   {
    "id": "23",
    "name": "Stefan Jauker",
    "links": [
     {
     "rel": "self",
     "href": "/api/v1/drivers/23"
    }
   ]
  }
 ]
}

7. 为集合提供过滤、排序、字段选择以及分页

过滤

为所有字段或者查询语句提供独立的查询参数:

GET /cars?color=red Returns a list of red cars
GET /cars?seats<=2 Returns a list of cars with a maximum of 2 seats

排序

允许跨越多字段的正序或者倒序排列:

GET /cars?sort=-manufactorer,+model

字段选择

一些情况下,我们只需要在列表中查询几个有标识意义的字段,我们不需要从服务端把所有字段的值都请求出来,所以需要支持API选择查询字段的能力,这也可以提到网络传输性能和速度:

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

分页

使用offset和limit来获取固定数量的资源结果,当其中一个参数没有出现时,应该提供各自的默认值,比如默认取第一页,或者默认取20条数据:

GET /cars?offset=10&limit=5
GET /cars?&limit=5  //Get first five result
GET /cars?&offset=5  //Get default amount result offset 5

使用自定义的头X-Total-Count发回给调用段实际的资源数量。

前一页后一页的链接也应该在HTTP头链接中得到支持,遵从下文中的链接原则而不要构建你自己的头:

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",

8. 版本化你的API

确保强制实行API版本,并且不要发布一个没有版本的API,使用简单的序列数字,避免使用2.5.0这样的形式:

/blog/api/v1

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

忽略错误处理的API是很难使用的,简单的返回500和调用堆栈是非常不友好也非常无用的:

使用HTTP状态码

HTTP标准提供了70多个状态码来描述返回值,我们不需要完全用到他们,下文中列出10个使用率较高的:

200 – OK – 一切正常 201 – OK – 新资源已经被创建 204 – OK – 资源删除成功

304 – 没有变化,客户端可以使用缓存数据

400 – Bad Request – 调用不合法,确切的错误应该在error payload中描述,例如:“JSON 不合法 ” 401 – 未认证,调用需要用户通过认证 403 – 不允许的,服务端正常解析和请求,但是调用被回绝或者不被允许 404 – 未找到,指定的资源不存在 422 – 不可指定的请求体 – 只有服务器不能处理实体时使用,比如图像不能被格式化,或者重要字段丢失。

500 – Internal Server Error – 标准服务端错误,API开发人员应该尽量避开这种错误

使用 error payloads

所有的异常都应该被映射到error payloads中,下文中的例子是一个json payload的模板:

{
  "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"
   }
  ]
}&nbsp;

10. 允许重写HTTP方法

一些代理只支持GET和POST方法,为了在这种限制下支持RESTful API,API需要重写HTTP方法。

使用自定义的X-HTTP-Method-Override  HTTP头来重写POST方法。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏博客园

Asp.Net Web API(二)

当然,你也可以创建一个Web API项目,利用 Web API模板,Web API模板使用 ASP.Net MVC提供API的帮助页。

701
来自专栏大内老A

并发与实例上下文模式: WCF服务在不同实例上下文模式下具有怎样的并发表现

通过《上篇》介绍,我们知道了如何通过编程和配置的方式设置相应的最大并发量,从而指导WCF的限流体系按照你设定的值对并发的服务调用请求进行限流控制。那么,在WCF...

1806
来自专栏aoho求索

Spring Cloud Gateway中的过滤器工厂:重试过滤器

Spring Cloud Gateway基于Spring Boot 2,是Spring Cloud的全新项目,该项目提供了一个构建在Spring 生态之上的AP...

1132
来自专栏刘望舒

Android网络编程(九)Retrofit2前篇[基本使用]

前言 Retrofit是Square公司开发的一款针对Android网络请求的框架,Retrofit2底层基于OkHttp实现的,而OkHttp现在已经得到Go...

1816
来自专栏JMCui

SpringMVC 与 REST.

    我敢打赌这并不是你第一次听到或读到REST这个词。当讨论REST时,有一种常见的错误就是将其视为“基于URL的Web服务”—— 将REST作为另一种类型...

814
来自专栏西安-晁州

redis中的发布订阅(Pub/Sub)

这里使用nodejs的redis模块说明,具体可见https://www.npmjs.com/package/redis ,先来通过一个简单的例子了解下redi...

2930
来自专栏阿杜的世界

会话管理

Http协议是无状态协议,Web服务器没有短期记忆。在有些应用场景(例如:购物车)下,需要跨越多个请求识别同一个客户——客户跟踪,在Web应用中使用Cookie...

332
来自专栏java一日一条

servlet/filter/listener/interceptor区别与联系

由于最近两个月工作比较清闲,个人也比较“上进”,利用工作空余时间,也继续学习了一下,某天突然想起struts2和struts1的区别的时 候,发现 为什么st...

452
来自专栏大内老A

ASP.NET应用下基于SessionState的“状态编程框架”解决方案

在一个基于ASP.NET的Web应用程序中,我们通常使用SessionState保存基于某个客户端的状态信息。但是这种单纯使用SessionState的编程方式...

1809
来自专栏大内老A

并发与实例上下文模式: WCF服务在不同实例上下文模式下具有怎样的并发表现

通过《上篇》介绍,我们知道了如何通过编程和配置的方式设置相应的最大并发量,从而指导WCF的限流体系按照你设定的值对并发的服务调用请求进行限流控制。那么,在WCF...

1836

扫码关注云+社区