Advertisement

RESTful APIs: How to Design, Develop, and Document them

阅读量:

作者:禅与计算机程序设计艺术

1.简介

HTTP 基础服务实现了 RESTful 规范。这种技术旨在创建、构建以及保护面向资源的 Web 服务接口。下面列出其主要特性:

URI(Uniform Resource Identifier):以统一资源标识符(URI)作为资源路径的标识;

  1. 请求方法(HTTP Methods):包括 GET、POST、PUT、DELETE等常用请求方法;

  2. 状态码(Status Codes):采用状态码进行响应信息交流;

  3. 数据格式(Data Formats):支持多种数据格式,如 JSON、XML、YAML、HTML 等;

HATEOAS(基于应用状态的超媒体引擎):支持客户端通过服务端获取所需的信息;

  1. 可伸缩性:能够应对负载增加或减少的情况。

RESTful API提供了功能完善的解决方案,并有助于降低系统间耦合程度并增强系统的扩展能力。然而其学习曲线较为陡峭 在实际应用中仍面临诸多挑战 因此掌握RESTful API的设计与实现方法、文档编写以及管理维护等技术要点是一个关键能力 本文将基于《RESTful API设计指南》(由孙博杰所著)作为教材 构建系统的知识体系框架 并深入探讨其中的技术要点和实现细节 通过深入研究这本书的内容 你可以系统地掌握相关技术知识

  • 理解RESTful API的基本概念和相关术语;

  • 掌握RESTful API的构建块,并了解其优缺点;

  • 了解RESTful API的规范约束,并熟练使用工具编写API定义文件;

  • 在实际项目中运用RESTful API时,遇到的一些实际问题及解决办法;

  • 有针对性地总结和分析RESTful API的最佳实践;

  • 掌握如何快速有效地进行API设计和开发,并能做好文档工作。

除了上述内容外, 本书还详细介绍了RESTful API错误处理机制, 帮助读者深入掌握API调用中的常见错误处理方式。本书不仅限于RESTful API, 还扩展介绍了其他相关技术, 如GraphQL、RPC等Web服务技术。通过系统学习本书, 你将全面掌握RESTful API的设计、实现、文档编写及最佳实践应用方法。最终, 你将对RESTful API的设计与开发有更加深入的理解, 并且有助于提升职场竞争力的编程人才。

2.基本概念术语说明

2.1 RESTful API简介

RESTful API是一种遵循HTTP协议的标准接口规范,在客户端与服务器之间建立数据交互通道。其主要特点包括以下几个方面:首先支持资源定位功能;其次具备状态监控机制;最后能够实现完整的数据交换流程。

统一接口:客户端与服务器之间的通信接口基于定位机制(Resource Locator)、统一资源标识(URI)以及不同的请求方式(如GET、POST、PUT和DELETE)。...原样保留。

  1. Stateless:无状态的,也就是没有保存之前请求的上下文信息;

  2. Cacheable:缓存功能,支持请求结果的缓存,减少网络IO;

Client–Server:在该架构中存在客户端与服务器之间的交互模式,在这种模式下服务器负责存储数据,并由客户端通过特定接口调用这些数据;

  1. Layered System:分层结构,各层自上而下逐层叠加;

  2. Code on Demand(optional):按需代码,客户端请求所需的代码;

  3. Hypermedia serves as the backbone for managing and organizing application states within a distributed system, referred to as HATEOAS. 作为支持分布式系统中应用状态管理的核心机制,在超媒体环境中实现了一种称为HATEOAS的技术架构。该架构通过整合多态性和异步性特性,在统一的网络层面上实现对不同平台和设备的应用状态的一致性管理。 从而实现了客户端无需手动查询即可识别和连接到服务的其他端点。

2.2 核心概念

2.2.1 资源(Resources)

RESTful API指导原则中最重要的一环就是资源(Resources)。简单来说,资源就是待处理的对象信息库中的实体信息包集中展示出来的东西,比如用户信息、订单数据等具体实例。每一个资源都有一个唯一的标识符,可以直接通过该标识符访问对应的资源信息包集体中展示出来的东西,比如获取某个用户的详细信息可以通过http://api.example.com/users/{userId}来访问。

2.2.2 方法(Methods)

方法是用来对资源进行操作的动作,目前常用的HTTP方法有如下四个:

  1. GET:获取资源,通常用于读取数据;

  2. POST:创建资源,通常用于新增数据;

  3. PUT:更新资源,通常用于修改数据;

  4. DELETE:删除资源,通常用于删除数据。

每个操作对应不同的功能,在处理具体事务时需要依据多种因素进行判断和选择。具体来说,在执行某个事务时需要考虑的因素包括:基于资源的状态、基于位置信息、基于历史记录数据以及基于锁定状态等因素来决定相应的操作方式。例如,在获取用户信息时采用GET操作,在完成用户的修改流程后则采用PUT操作以实现数据更新。

2.2.3 请求(Requests)

请求一般由以下几个部分构成:

标题栏(Header):标题栏包含了许多关键信息如元数据字段如常见的字段包括但不限于:Content-Type、Authorization和Content-Length等。

查询字符串(Query String):查询字符串通常用作过滤条件;常被用来筛选出符合条件的资源集合。

请求体(Body):在通常情况下,在创建新的资源或进行现有资源的更新时所涉及的内容即为请求体的一部分。

2.2.4 响应(Responses)

响应一般由以下几个部分构成:

在Header部分中包含着关键的元数据信息,如Content-Type、Cache-Control和Expires等字段。

状态代码(Status Code):用来表示请求的状态信息,在网络通信中通常由服务器返回给客户端以指示操作结果;
常见的状态代码包括:

  • 2XX(成功):表示请求操作已完成并返回响应;
  • 3XX(重定向):用于指示客户端应执行的重定向操作;
  • 4XX(客户端错误):表明客户端发生了错误;
  • 5XX(服务器错误):表明服务器发生了错误;

响应体(Body):响应体中包含请求结果的具体信息,并采用JSON数据结构、XML文档形式、HTML标记语言以及纯文本内容等多种表现方式。

2.2.5 参数(Parameters)

消息字段是对请求或响应消息中特定值的描述性标识符,在系统运行过程中起到明确区分作用。这些字段通常用于设定过滤标准如数据筛选条件,在线页码定位或其他排序规则,并可在不同名称或存储位置上实现统一管理以适应多样性需求。在URL路径上可设置固定位置,在数据体中可作为正文内容,在头部可作为元数据标识,在查询串中可作为筛选依据,并支持任何形式的数据类型存储与传输

2.2.6 关系(Relationships)

关联是指两个资源之间存在的联系。它可能是静态的(如用户的角色),也可能是动态的(如用户生成一个新的订单请求)。通常通过链接的方式来建立这种关联关系,并且可以通过orders?userId=xxx接口获取相关信息。

2.2.7 子资源(Subresources)

子资源是一种特殊的类型关系,在这种关系下能够将相关的操作放置于包含其他资源的嵌套URI中,并降低API调用中的嵌套层级。例如,在该系统中处理用户信息时会使用这种子资源结构

2.2.8 URL模式

URL的结构决定了资源的可用性。它应该尽可能简洁明了,并以避免冗余和歧义的方式进行设计。例如,在HTTP URL路径中使用{users}/{id}/orders/这一命名方式表示对用户的订单信息进行访问操作:通过该路径可以获取单个用户的订单列表信息(即该用户的所有订单),但无法查看不同用户之间的订单列表信息(即不同用户的所有订单)。

2.2.9 MIME Types

2.2.10 状态码

HTTP编码(Status Code)用于指示HTTP请求的响应结果。常见编码类型主要包括以下几个方面:

  1. 成功响应(例如200 OK、201 Created、202Accepted 等);
  2. 重定向指令(包括301 Moved Permanently、302Found 等);
  3. 客户端错误(例如400 Bad Request、401Unauthorized 等);
  4. 服务器错误(例如500 Internal Server Error 等)。

3.核心算法原理及其具体操作步骤以及数学公式讲解

RESTful API的主要目标是使其接口更加灵活,并能够使得第三方应用程序更容易地进行使用。下面将详细阐述RESTful API的核心原理及其具体的实现步骤。

3.1 标识符

RESTful API的URL一般遵循如下的命名规范:

该链接的URL路径中包含三个参数字段:版本号(以[version]表示)、资源信息(以[resource]表示)以及标识符(以[identifier]表示)。这三个字段分别由方括号包裹,并通过编码转换为对应的字符

其中,

3.2 描述性状态码

在HTTP协议中定义的状态码是用来表示请求结果是否成功的代码集合。根据这些代码值的不同含义可以将它们划分为不同的类别以区分不同类型的网络操作结果。其中最常见的几种状态代码包括2xx成功系列、3xx重定向系列、4xx客户端错误系列以及5xx服务器错误系列等。
以下将介绍几种具有特殊意义的状态码。

3.2.1 创建(201 CREATED)

表示已经成功创建了新的资源。

3.2.2 已删除(204 NO CONTENT)

表示请求被成功处理,但响应主体为空,用来表示删除操作成功。

3.2.3 非授权(401 UNAUTHORIZED)

表示用户没有权限执行指定的操作,类似403 Forbidden。

3.2.4 禁止访问(403 FORBIDDEN)

表明请求被服务器拒绝执行的原因是无法获取所需资源的必要访问权限,如仅读权限等。

3.2.5 不存在(404 NOT FOUND)

表示服务器找不到请求的资源,类似404 Not Found。

3.2.6 请求超时(408 REQUEST TIMEOUT)

该应用程序因服务器应答时间不足而被拒绝连接请求,并与504错误码类似。

3.2.7 冲突(409 CONFLICT)

表示请求无法被完成,因为数据库中已存在相同的数据。

3.2.8 预期失败(417 EXPECTATION FAILED)

表示请求失败,因为服务器无法满足Expect的请求头信息。

3.2.9 未认证(401 UNAUTHORIZED)

表示用户未提供身份验证凭据,类似401 Unauthorized。

3.2.10 未授权(403 FORBIDDEN)

表示用户已登录但没有权限访问指定的资源,类似403 Forbidden。

3.2.11 不接受(406 NOT ACCEPTABLE)

表明请求资源的内容特性不满足请求头的条件, 如同406 Not Acceptable

3.2.12 冲突(409 CONFLICT)

表明请求失败的原因是由于资源的状态或请求中的参数设置存在冲突,并类似于HTTP 409 Conflict错误。

3.2.13 长度限制(413 ENTITY TOO LARGE)

该服务器表明不接受超出其支持范围的请求

3.2.14 拒绝范围(416 RANGE NOT SATISFIABLE)

当客户端请求的有效范围不正确时

3.2.15 语法错误(400 BAD REQUEST)

表示客户端发送的请求存在语法错误,并非技术规格或服务端问题所在;其中参数和消息体格式等细节未达到规范要求;与HTTP 400错误响应类似,并且HTTP 400错误响应通常用于指示客户端提交了无效或不完整的请求。

3.2.16 升级 Required(426 Upgrade Required)

表示客户端应当切换至TLS/1.0。

3.2.17 内部错误(500 INTERNAL SERVER ERROR)

表明由于服务器端出现故障而导致了请求未能成功。其中服务器端通常会返回500 Internal Server Error作为错误信息。

3.2.18 服务不可用(503 SERVICE UNAVAILABLE)

服务器当前正处于超载状态或 undergoes maintenance. 该服务通常无法响应请求并返回HTTP状态码503 Service Unavailable.

3.3 使用HTTP方法

HTTP协议采用多种手段来执行各种操作;这些操作包括GET(获取)、POST(提交)、PUT(更新)、PATCH(部分更新)和DELETE(删除)等。

3.3.1 GET

用于获取资源,常用于查询,不需要提交任何内容,一般用于获取数据。

示例:

复制代码
    GET /users HTTP/1.1
    Host: api.example.com
    Accept: application/json
    
      
      
    
    代码解读

3.3.2 POST

用于建立资源的系统中将被提交的数据会被存储在服务器上;涉及需要提交资源的实体通常会进行插入操作。

示例:

复制代码
    POST /users HTTP/1.1
    Host: api.example.com
    Content-Type: application/json
    Content-Length: 41
    
    {
      "name": "Alice",
      "email": "alice@gmail.com"
    }
    
      
      
      
      
      
      
      
      
    
    代码解读

3.3.3 PUT

用于更新资源,提交的数据完全替换掉旧数据,一般用于修改。

示例:

复制代码
    PUT /users/123 HTTP/1.1
    Host: api.example.com
    Content-Type: application/json
    Content-Length: 41
    
    {
      "name": "Bob",
      "email": "bob@gmail.com"
    }
    
      
      
      
      
      
      
      
      
    
    代码解读

3.3.4 PATCH

表示一个用于更新资源的字段,在这种情况下,提交的数据与其它属性之间没有关联,并且该字段通常用于对局部数据进行修改

示例:

复制代码
    PATCH /users/123 HTTP/1.1
    Host: api.example.com
    Content-Type: application/json
    Content-Length: 23
    
    {
      "age": 30
    }
    
      
      
      
      
      
      
      
    
    代码解读

3.3.5 DELETE

用于删除资源,一般用于删除数据。

示例:

复制代码
    DELETE /users/123 HTTP/1.1
    Host: api.example.com
    
      
    
    代码解读

4.具体代码实例及其解释说明

随后, 我将向大家演示常见RESTful API的具体实现方案. 接下来我们将深入探讨API路由的定义方式, 以及如何通过合理的配置确保服务之间的高效通信.

4.1 定义路由

在RESTful APIs中,路由由URL来实现对请求的匹配以及对相关操作的处理。以下是如何定义API路由的方法

4.1.1 概念

网络路由是指对特定服务或数据项的请求所使用的URL地址以及处理该请求的方法的一种映射关系。根据预先定义好的网络路由配置,客户端系统可以通过指定的URL地址来访问相应的服务或数据项,并促使服务器执行相应的操作。

4.1.2 用途

  • 支持RESTful API接口;
    • 通过使用正则表达式对URL进行匹配操作,从而实现URL资源的可复用性;
    • 基于请求头信息和客户端特征(如IP地址、User Agent和Referer),实施访问权限控制。

4.1.3 语法

路由一般采用如下的语法:

复制代码
    app.METHOD(PATH, HANDLER);
    
    
    代码解读
  • app:指定了Express框架中的一个应用实例;
    • METHOD:包含了各种HTTP请求方法集合;
    • PATH:表示HTTP请求中的路径信息;
    • HANDLER:负责响应特定HTTP请求类型的处理函数。

4.1.4 Express路由

Express框架集成了一些路由模块,并支持方便地创建RESTful API。以下列举了常见的几种常用路由配置方式:

4.1.4.1 通配符路由

通配符路由是指可以使用星号作为占位符,匹配任意字符。

复制代码
    // 匹配 /users 和 /users/123
    app.get('/users/*', function (req, res) {
      //...
    });
    
      
      
      
    
    代码解读
4.1.4.2 参数路由

parameter routing主要采用在路径定义中使用:token标签指定的方式,并实现了对请求参数资源的配置。

复制代码
    // 匹配 /users/123
    app.get('/users/:id', function (req, res) {
      var userId = req.params.id;
      //...
    });
    
      
      
      
      
    
    代码解读
4.1.4.3 自定义中间件

Express框架中的中间件功能具备对请求与响应施加钩子的能力,并不仅具备针对请求与响应实施拦截处理的能力;同时支持定制化的日志记录方案

复制代码
    function loggerMiddleware(req, res, next) {
      console.log('Request received');
      next();
    }
    
    app.use(loggerMiddleware);
    
      
      
      
      
      
    
    代码解读
4.1.4.4 文件上传

Express框架支持文件上传功能,可以接收客户端发送的文件。

复制代码
    app.post('/upload', function (req, res) {
      if (!req.files || Object.keys(req.files).length === 0) {
    return res.status(400).send('No files were uploaded.');
      }
    
      // The name of the input field (i.e. "photo") is used to retrieve the uploaded file
      let sampleFile = req.files.sampleFile;
    
      // Use the mv() method to place the file somewhere on your server
      sampleFile.mv(__dirname + '/uploads/' + sampleFile.name, function (err) {
    if (err)
      return res.status(500).send(err);
    
    res.send('File uploaded successfully!');
      });
    });
    
      
      
      
      
      
      
      
      
      
      
      
      
      
      
      
    
    代码解读

4.2 获取资源

接下来,我们来看一下如何通过GET方法获取资源。

4.2.1 概念

获取资源是指客户端通过HTTP GET方法请求服务器上的资源。

4.2.2 用途

  • 检索服务器上的数据;
  • 浏览网站目录;
  • 查看表单、网页上的内容。

4.2.3 请求示例

假设有一张表,存储着用户信息。我们想从服务器上获取所有的用户信息。

复制代码
    GET /users HTTP/1.1
    Host: example.com
    
      
    
    代码解读

4.2.4 返回示例

服务器会返回一个JSON数组,包含所有用户的信息。

复制代码
    [
      {"id": 123, "name": "Alice", "email": "alice@gmail.com"},
      {"id": 456, "name": "Bob", "email": "bob@yahoo.com"}
    ]
    
      
      
      
    
    代码解读

4.3 创建资源

现在,我们来看一下如何通过POST方法创建资源。

4.3.1 概念

创建资源是指客户端通过HTTP POST方法向服务器提交新资源。

4.3.2 用途

  • 添加新资源;
  • 修改现有资源;
  • 提交表单、上传文件等。

4.3.3 请求示例

假设有一个表单,客户端提交了用户名、邮箱等信息。

复制代码
    POST /users HTTP/1.1
    Host: example.com
    Content-Type: application/x-www-form-urlencoded
    
    username=Alice&email=alice%40gmail.com
    
      
      
      
      
    
    代码解读

4.3.4 返回示例

服务器会返回一个JSON对象,包含刚才创建的资源的详细信息。

复制代码
    {"id": 123, "name": "Alice", "email": "alice@gmail.com"}
    
    
    代码解读

4.4 更新资源

现在,我们来看一下如何通过PUT方法更新资源。

4.4.1 概念

更新资源是指客户端通过HTTP PUT方法更新服务器上的资源。

4.4.2 用途

  • 替换服务器上原有的资源;
  • 更改多个资源的属性。

4.4.3 请求示例

假设有一条用户信息,需要更改邮箱地址。

复制代码
    PUT /users/123 HTTP/1.1
    Host: example.com
    Content-Type: application/json
    
    {"email": "new_email@example.com"}
    
      
      
      
      
    
    代码解读

4.4.4 返回示例

当进行一次成功的更新操作时

4.5 删除资源

最后,我们来看一下如何通过DELETE方法删除资源。

4.5.1 概念

删除资源是指客户端通过HTTP DELETE方法删除服务器上的资源。

4.5.2 用途

  • 从服务器上永久删除资源;
  • 清空资源的集合。

4.5.3 请求示例

假设有一条用户信息,需要删除。

复制代码
    DELETE /users/123 HTTP/1.1
    Host: example.com
    
      
    
    代码解读

4.5.4 返回示例

如果删除操作顺利完成,则服务器将返回一个空响应字段。相反地,在无法完成删除操作时,服务器将返回相应的错误信息。

5.未来发展趋势与挑战

随着时间的发展, RESTful API的概念已获得广泛应用.近年来, RESTful API被视为分布式系统和微服务架构的标准配置,是所有Web技术栈的基础.然而, RESTful API仍存在诸多细节与规范问题,在实践中也面临着诸多挑战.以下将阐述未来的发展方向及面临的挑战.

5.1 模型驱动API生成

目前,在现有的框架体系中均具备代码自动生成功能的能力。这项工作不仅可大幅降低开发人员的工作负担,并显著提升了系统运行效率;同时更为前后端分离的发展提供了有力的技术支持基础。然而,在性能优化、可靠性提升以及安全性保障等方面仍有较大的改进空间存在

5.2 GraphQL

GraphQL是由Facebook于2015年推出的基于GraphQL查询语言的Web应用程序接口(API)规范性文件体系,在致力于实现强大的数据查询能力方面取得了显著成就。与传统 RESTful APIs相比,在遵循单体架构的传统RESTfulAPI框架下, GraphQL展现出更高的性能水平, 并通过灵活的数据模型和易于管理的数据依赖关系实现了更具竞争力的功能配置.随着分布式系统和微服务架构的发展,QPLA正逐步成为这一领域中的主流选择,同时也可能保留传统RESTfulAPI的一些设计理念.

5.3 RPC

Remote Procedure Call(简称RPC)作为分布式系统间的信息传递机制,在实际应用中具有独特的优势与价值。该机制的核心特性是实现一次远程过程调用,在这种模式下客户端主要负责进程调度工作而无需直接处理服务提供细节;服务器则专注于提供所需服务即可满足需求。就目前而言,在分布式系统开发中较为流行的RPC框架包括Apache Thrift和gRPC等;就未来发展趋势而言随着RESTful API在Web开发中占据主导地位,在未来一段时间内基于RESTful API实现的 RPC 将会成为重要的替代方案之一。

5.4 速率限制

RESTful API的访问速率受限于流量高峰时段的影响,在这种情况下必须实施速率限制措施以优化性能表现。此外,在安全性方面的一些企业开始采用OAuth、JWT等标准认证机制来加强API的安全防护。

5.5 流量管理

RESTful API的使用频率、吞吐量受限以及处理能力极端高,因此亟需实施流量管理策略。目前而言,在开源领域中服务网关领域存在诸多挑战亟待解决。

6.附录

6.1 API设计常见误区

6.1.1 嵌套过深

API的层次过于复杂将直接导致 URL变得冗杂且难以管理,并最终显著影响 API 的可用性和性能表现。

6.1.2 不充分利用URIs

通常情况下,在API中表示资源路径的URL往往仅反映基础路径信息,并未充分利用URI所具有的潜在功能。例如:获取资源的状态码、返回相关资源等信息。

  • 采用同义词或别名来提升URL的友好性和易懂性;
  • 通过内容协商降低客户端与服务器之间的协调需求;
  • 采用查询字符串参数从而帮助客户端实现资源筛选、搜索等功能;
  • 利用状态码传递更具意义的错误信息以提高系统可靠性。

6.1.3 没有正确地处理请求

在API处理请求的过程中,需综合考量客户端输入、服务器端权限以及服务器端处理机制等多个维度的因素,并保证API的安全运行与可靠服务。

6.1.4 没有正确地使用响应

在API的响应阶段中,应明确定义响应格式、状态码和头信息,并确保客户端能够正确解析这些数据。

6.1.5 API设计规范与工具

目前来看,在API领域已形成了系列的设计规范和工具体系。其中一些包括但不限于OpenAPI、RAML和Swagger等。这些规范和技术将进一步推动整个API领域向着更加统一的方向发展,并显著地增强其可用性、易用性和可扩展性。

全部评论 (0)

还没有任何评论哟~