RESTful 接口实现简明指南

简介: 在前后端分离的 Web 应用架构中,前端专注于页面,同时与后端进行数据交互;而后端则专注于提供 API 接口。在这样的结构下,REST 是一个很流行的前后端交互形式的约定。这只是一套约定,并不是某个技术标准,所以在实际的应用中,对器实现程度完全取决于后端开发者;一些号称 RESTful 的接口并没有那么RESTful。

在前后端分离的 Web 应用架构中,前端专注于页面,同时与后端进行数据交互;而后端则专注于提供 API 接口。在这样的结构下,REST 是一个很流行的前后端交互形式的约定。这只是一套约定,并不是某个技术标准,所以在实际的应用中,对器实现程度完全取决于后端开发者;一些号称 RESTful 的接口并没有那么RESTful。

在我所见过的 RESTful 接口的实现中,以 GitHub 最让人惊叹。我第一次如此强烈得感受到 REST 接口的美妙,完全满足了我所期待的「接口的形式美感」,简直就是对 REST 规范实现的最佳范本。我觉得每一个后端开发者都应该看一看 GitHub 的 REST 接口文档,感受一下循规蹈矩的美妙。

本文选取了几个点来简要介绍,一个让前端开发者用起来舒服的 RESTful 接口是什么样子。

REST 简介
以防有些观众刚刚打开电梯,还是有必要简单介绍一下 REST 这个概念。

REST 是一个术语的缩写,REpresentational State Transfer,中文直译「表征状态转移」,这是个很拗口的词。我的建议是先不要强行理解,直接看怎么做,等对实施细节有一些了解后,再来看名字会有更深刻的理解。REST 是一套风格约定,RESTful 是它的形容词形式;比如一套实现了 REST 风格的接口,可以称之为 RESTful 接口。

REST 对请求的约定
REST 用来规范应用如何在 HTTP 层与 API 提供方进行数据交互;在现阶段,你应该已经很熟悉 GET 和 POST 请求;甚至有可能因为受限于后端框架限制等原因,你的整个应用全都是用这两种 HTTP 方法来完成的。这样无疑浪费了 HTTP 协议的潜力,而 REST 则充分利用了 HTTP 规范中的方法,达到接口描述的语义化。

REST 描述了 HTTP 层里客户端和服务器端的数据交互规则;客户端通过向服务器端发送 HTTP(s)请求,接收服务器的响应,完成一次 HTTP 交互。这个交互过程中,REST 架构约定两个重要方面就是 HTTP 请求的所采用方法,以及请求的链接。

在请求层面,REST 规范可以简单粗暴抽象成以下两个规则:

  1. 请求 API 的 URL 表示用来定位资源;
  2. 请求的 METHOD 表示对这个资源进行的操作;

以下将以这两个规则为基础,描述如何构造一个符合 REST 规范的请求。

一、API 的 URL

URL 用来定位资源,跟要进行的操作区分开,这就意味这 URL 不该有任何动词;

下面示例中的 get、create、search 等动词,都不应该出现在 REST 架构的后端接口路径中。在以前,这些接口中的动名词通常对应后台的某个函数。比如:

/api/getUser
/api/createApp
/api/searchResult
/api/deleteAllUsers

当我们需要对单个用户进行操作时,根据操作的方式不同可能需要下面的这些接口:

/api/getUser (用来获取某个用户的信息,还需要以参数方式传入用户 id 信息)
/api/updateUser (用来更新用户信息)
/api/deleteUser (用来删除单个用户)
/api/resetUser (重置用户的信息)

更有甚者,可能在更新用户不同信息时,提供不同的接口,比如:

/api/updateUserName
/api/updateUserEmail
/api/updateUser

这样的弊端在于:首先加上了动词,肯定是使 URL 更长了;其次对一个资源实体进行不同的操作就是一个不同的 URL,造成 URL 过多难以管理。

其实当你回过头看「URL」 这个术语的定义时,更能理解这一点。URL 的意思是统一资源定位符,这个术语已经清晰的表明,一个 URL 应该用来定位资源,而不应该掺入对操作行为的描述。

在 REST 架构的链接应该是这个样子:

URL 中不应该出现任何表示操作的动词,链接只用于对应资源;

URL 中应该单复数区分,推荐的实践是永远只用复数;比如 GET /api/users 表示获取用户的列表;如果获取单个资源,传入 ID,比如 /api/users/123 表示获取单个用户的信息;

按照资源的逻辑层级,对 URL 进行嵌套,比如一个用户属于某个团队,而这个团队也是众多团队之一;那么获取这个用户的接口可能是这样:

GET /api/teams/123/members/234 表示获取 id 为 123 的小组下,id 为234 的成员信息

按照类似的规则,可以写出如下的接口

/api/teams (对应团队列表)
/api/teams/123 (对应 ID 为 123 的团队)
/api/teams/123/members (对应 ID 为 123 的团队下的成员列表)
/api/teams/123/members/456 (对应 ID 为 123 的团队下 ID 未 456 的成员)

二、API 请求的方法

在很多系统中,几乎只用 GET 和 POST 方法来完成了所有的接口操作;这个行为类似于全用 DIV 来布局。实际上,我们不只有GET 和 POST 可用,在 REST 架构中,有以下几个重要的请求方法:GET,POST,PUT,PATCH,DELETE。这几个方法都可以与对数据的 CRUD 操作对应起来。

【Read】 资源的读取,用 GET 请求;比如:

GET /api/users ( 表示读取用户列表)

GET 应当实现为一个安全方法。用于获取数据而不应该产生副作用。

【Created】资源的创建,用 POST 方法;

POST 是一个非幂等的方法,多次调用会造成不同效果;

幂等(Idempotent):如果对服务器资源的多次请求与一次请求造成的副作用是一样的的话,那这个请求方法可以被认为是幂等。

比如下面的请求会在服务器上创建一个 name 属性为 'John Snow' 的用户;多次请求就会创建多个这样的用户。

POST /api/users
{
"name": "John Snow"
}

【Update】资源的更新,用于更新的 HTTP 方法有两个,PUT 和 PATCH。

他们都应当被实现为幂等方法,即多次同样的更新请求应当对服务器产生同样的副作用。

PUT 和 PATCH 有各自不同的使用场景:

PUT 用于更新资源的全部信息,在请求的 body 中需要传入修改后的全部资源主体;

而 PATCH 用于局部更新,在 body 中只需要传入需要改动的资源字段。

设想服务器中有以下用户资源 /api/users/123

{
"id": 123,
"name": "Original",
"age": 20
}

当我们往后台发送更新请求时,PATCH 和 PUT 造成的效果是不一样。

PUT /api/users/123
{
"name": "PUT Update"
}

上述 PUT 请求操作后的内容是:

{
"id": 123,
"name": "PUT Update"
}

可以观察到,资源原有的 age 字段被清除掉了。

而如果改用 PATCH 的话,

PATCH /api/users/123
{
"name": "PATCH Update"
}

更新后的内容是:

{
"id": 123,
"name": "PATCH Update",
"age": 20
}

请求中指定的 name 属性被更新了,而原有的 age 属性则保持不变。

PATCH 的作用在于如果一个资源有很多字段,在进行局部更新时,只需要传入需要修改的字段即可。否则在用 PUT 的情况下,你不得不将整个资源模型全都发送回服务器,造成网络资源的极大浪费。

【Delete】资源的删除,相应的请求 HTTP 方法就是 DELETE。这个也应当被实现为一个幂等的方法。如:

DELETE /api/users/123

用于删除服务器上 ID 为 123 的资源,多次请求产生副作用都是,是服务器上 ID 为 123 的资源不存在。

三、分页、过滤

REST 风格的接口地址,表示的可能是单个资源,也可能是资源的集合;当我们需要访问资源集合时,设计良好的接口应当接受参数,允许只返回满足某些特定条件的资源列表。

比如支持以 offset 和 limit 参数来进行分页;

GET /api/users?offset=0&limit=20

支持提供关键词进行搜索,以及排序

GET /api/users?keyword=john&sort=age

支持根据字段进行过滤

GET /api/users?gender=male

设计合适的 API URL,以及选择合适的请求方法,可以语义化的描述一个 HTTP 请求的操作。

当我们都熟悉且遵循这样的规范后,基本可以看到一个 REST 风格的接口就知道如何使用这个接口进行 CRUD 操作了。比如下面这面这个接口就表示搜索 ID 为 123 的图书馆的书,并且书的信息里包含关键字「game」,返回前十条满足条件的结果。

GET /api/libraries/123/books?keyword=game&sort=price&limit=10&offset=0

同样,下面这个请求的意思也就很明显了吧。

PATCH /api/companies/123/employees/234
{

"salary": 2300

}

总结

限于篇幅限制,本文仅从请求的角度选取了几个重点描述了实现 RESTful 接口需要满足的基本要求。关于 REST 的更多详细规范库https://github.com/aisuhua/restful-api-design-references

原文发布时间为:2018-06-27
本文作者:ioslh
本文来自云栖社区合作伙伴“Web项目聚集地”,了解相关信息可以关注“Web项目聚集地”。

相关文章
|
6月前
|
XML JSON 数据格式
flea-jersey使用之Flea RESTful接口客户端接入
本篇介绍 Flea框架下的 flea-jersey-client模块,并提供客户端依赖管理及接入步骤
58 1
flea-jersey使用之Flea RESTful接口客户端接入
|
6月前
|
API 网络架构 开发框架
flea-jersey使用之Flea RESTful接口服务端接入
本篇介绍 Flea框架下的 flea-jersey-server模块,并提供服务端依赖管理及接入步骤
69 1
flea-jersey使用之Flea RESTful接口服务端接入
|
5月前
|
XML 物联网 API
服务端和客户端 RESTful 接口上传 Excel 的 Python 代码
本文作者木头左是物联网工程师,分享如何使用 Python 和 Flask-RESTful 构建一个简单的 RESTful API,实现文件上传功能,特别支持Excel文件。通过安装Flask和Flask-RESTful库,创建Flask应用,实现文件上传接口,并将其添加到API。该方法具有简单易用、灵活、可扩展及社区支持等优点。
服务端和客户端 RESTful 接口上传 Excel 的 Python 代码
|
2月前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
104 6
|
3月前
|
XML JSON API
RESTful API设计最佳实践:构建高效、可扩展的接口
【8月更文挑战第17天】RESTful API设计是一个涉及多方面因素的复杂过程。通过遵循上述最佳实践,开发者可以构建出更加高效、可扩展、易于维护的API。然而,值得注意的是,最佳实践并非一成不变,随着技术的发展和业务需求的变化,可能需要不断调整和优化API设计。因此,保持对新技术和最佳实践的关注,是成为一名优秀API设计师的关键。
|
4月前
|
API 数据安全/隐私保护 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
【7月更文挑战第23天】Python的RESTful API设计在Web开发中流行,提升效率与体验。REST强调HTTP方法(GET, POST, PUT, DELETE)操作资源。使用Flask框架可快速实现API,如管理用户信息。示例代码展示如何创建、读取、更新和删除用户,通过不同HTTP方法和URL路径。实际应用中,增加验证、错误处理和权限控制可增强API的安全性和稳定性。安装Flask后,可运行代码测试API功能。
65 6
|
4月前
|
安全 API 网络架构
Python RESTful API设计新篇章,打造高效、易用、安全的Web服务接口,你准备好了吗?
【7月更文挑战第22天】在数字化转型中,RESTful API借助Python的Flask和Django REST Framework,提供高效、易用和安全的接口设计。Flask示例展示了简洁的CRUD操作,Swagger等工具增进API文档的易用性,而HTTPS、JWT和输入验证确保安全性。Python RESTful API设计涉及效率、可用性和安全,是不断进化的Web服务接口的关键。准备好踏上这一新篇章了吗?一起探索,创造卓越!
61 2
|
5月前
|
存储 前端开发 安全
Nuxt3 实战 (十):使用 Supabase 实现 RESTful 风格 API 接口
这篇文章介绍了如何使用Supabase实现RESTful风格的API接口,用于网站分类和子站点的增删改查(CURD)功能。文章首先阐述了表设计,包括ds_categorys和ds_websites两张表的列名、类型和用途,并提到了为每张表添加的user_id和email字段以支持用户身份识别。接着,文章描述了接口设计,以ds_websites表为例,说明了如何通过RESTful API实现CURD功能,并给出了使用SupabaseClient实现插入数据的相关代码。文章最后提供了项目效果预览和总结,指出学习了Nuxt3创建接口及调用Supabase数据库操作。
Nuxt3 实战 (十):使用 Supabase 实现 RESTful 风格 API 接口
|
5月前
|
XML 安全 API
API攻防-接口安全&SOAP&OpenAPI&RESTful&分类特征导入&项目联动检测
API攻防-接口安全&SOAP&OpenAPI&RESTful&分类特征导入&项目联动检测
|
5月前
|
SQL 缓存 测试技术
RESTful API设计的最佳实践:构建高效、可维护的Web服务接口
【6月更文挑战第11天】构建高效、可维护的RESTful API涉及多个最佳实践:遵循客户端-服务器架构、无状态性等REST原则;设计时考虑URL结构(动词+宾语,使用标准HTTP方法)、使用HTTP状态码、统一响应格式及错误处理;确保数据安全(HTTPS、认证授权、输入验证);实施版本控制;并提供详细文档和测试用例。这些实践能提升Web服务接口的性能和质量。