REST和RESTful API简介

REST是代表状态转移的缩写,它是最常用的Web服务技术的几乎毫无意义的描述!REST是两个计算机系统通过HTTP进行通信的一种方式,类似于Web浏览器和服务器。

在两个或多个系统之间共享数据一直是软件开发的基本要求。例如,考虑购买汽车保险。您的保险公司必须获取有关您和您的车辆的信息,以便他们向汽车登记机构,信贷机构,银行和其他系统索取数据。所有这些实时透明地发生,以确定是否可以提供策略。

这篇颇受欢迎的文章在​​2020年进行了更新,以准确地解释现代REST API。

REST示例

在浏览器中打开以下链接,以请求一个随机编程笑话:

https://official-joke-api.appspot.com/jokes/programming/random

这是实现为RESTful Web服务的公共API(遵循REST约定)。您的浏览器将显示可怕的 JSON格式的编程笑话,例如:

[
  {
    "id": 29,
    "type": "programming",
    "setup": "There are 10 types of people in this world...",
    "punchline": "Those who understand binary and those who don't"
  }
]

您可以使用任何HTTP客户端(例如curl)来请求相同的URL并获得响应:

curl "https://official-joke-api.appspot.com/jokes/programming/random"

HTTP客户端库在所有流行的语言和运行时中都可用,包括JavaScript中的FetchPHP中的file_get_contents()。JSON响应是机器可读的,因此可以解析并以HTML或任何其他格式输出。

休息与休息

这些年来,各种数据通信标准都在发展。您可能会遇到包括CORBASOAPXML-RPC在内的标准,这些标准通常会建立严格的消息传递规则。

REST由Roy Fielding于2000年定义,并且相当简单。它不是标准,而是针对RESTful Web服务的一系列建议和约束。这些包括:

  1. 客户端服务器。SystemA向SystemB托管的URL发出HTTP请求,该URL返回响应。

    这与浏览器的工作方式相同。该应用程序请求一个特定的URL。该请求被路由到返回HTML页面的Web服务器。该页面可能包含对图像,样式表和JavaScript的引用,这些引用会导致进一步的请求和响应。

  2. 无状态的。REST是无状态的:客户端请求应包含响应请求所需的所有信息。换句话说,应该可以以任何顺序发出两个或多个HTTP请求,并且将接收到相同的响应。
  3. 可缓存。应将响应定义为可缓存或不可缓存。
  4. 分层。发出请求的客户端不需要知道它是否与实际的服务器,代理或任何其他中介进行通信。

创建一个RESTful Web服务

RESTful Web服务请求包含:

  1. 端点URL。实施RESTful API的应用程序将使用域,端口,路径和/或查询字符串(例如)定义一个或多个URL端点。https://mydomain/user/123?format=json
  2. HTTP方法。可以在映射到应用程序创建,读取,更新和删除(CRUD)操作的任何端点上使用不同的HTTP方法:
    HTTP方法 欺诈 行动
    得到 返回请求的数据
    开机自检 创建 创建新记录
    放置或修补 更新 更新现有记录
    删除 删除 删除现有记录

    例子:

    • GET请求以/user/返回系统上已注册用户的列表
    • POST请求以使用主体数据创建具有ID的用户/user/123123
    • 一个PUT请求,以用主体数据更新用户/user/123123
    • GET请求以返回用户的详细信息/user/123123
    • 删除用户的DELETE请求/user/123123
  3. HTTP标头。如信息的认证令牌或Cookie可以包含在HTTP请求报头。
  4. 身体数据。数据通常以与HTML 提交相同的方式在HTTP正文中传输,或通过发送单个JSON编码的数据字符串传输。<form>

响应

响应有效载荷可以是任何实用:数据,HTML,图像,音频文件,依此类推。数据响应通常是JSON编码的,但是可以使用XML,CSV,简单字符串或任何其他格式。您可以允许在请求中指定返回格式,例如或。/user/123?format=json/user/123?format=xml

还应该在响应头中设置适当的HTTP状态代码。尽管成功也可以在创建记录时返回,但它通常用于成功的请求。错误应该返回相应的代码,比如,,,等等。200 OK201 Created400 Bad Request404 Not Found401 Unauthorized

可以设置其他HTTP标头,包括Cache-ControlExpires指令,以指定在响应被认为过时之前可以将响应缓存多长时间。

但是,没有严格的规则。可以根据需要实现端点URL,HTTP方法,主体数据和响应类型。例如,POST,PUT和PATCH通常可以互换使用,因此任何人都可以创建或更新记录。

REST“ Hello World”示例

以下代码使用Node.js Express框架创建RESTful Web服务。单个/hello/端点响应GET请求。

确保已安装Node.js,然后创建一个名为的新文件夹restapi。在该文件夹中创建一个包含以下内容的新文件:package.json

{
  "name": "restapi",
  "version": "1.0.0",
  "description": "REST test",
  "scripts": {
    "start": "node ./index.js"
  },
  "dependencies": {
    "express": "4.17.1"
  }
}

运行npm install在命令行来获取相关性,则创建一个用下面的代码文件:index.js

// simple Express.js RESTful API
'use strict';

// initialize
const
  port = 8888,
  express = require('express'),
  app = express();

// /hello/ GET request
app.get('/hello/:name?', (req, res) =>
  res.json(
    { message: `Hello ${req.params.name || 'world'}!` }
  )
);

// start server
app.listen(port, () =>
  console.log(`Server started on port ${port}`);
);

使用从命令行启动应用程序,npm start然后在浏览器中打开。显示以下JSON以响应GET请求:http://localhost:8888/hello/

{
  "message": "Hello world!"
}

该API还允许使用自定义名称,因此返回:http://localhost:8888/hello/everyone/

{
  "message": "Hello everyone!"
}

客户端REST请求和CORS

考虑以下在浏览器中URL启动的HTML页面:http://localhost:8888/

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>REST test</title>
</head>
<body>
<script>
fetch('http://localhost:8888/hello/')
  .then((response) => {
    return response.json();
  })
  .then((json) => {
    console.log(json);
  });
</script>
</body>
</html>

fetch调用发出与您期望的相同的API请求和浏览器控制台。Object { message: "Hello world!" }

但是,假设您的RESTful Web服务现在已在域中的Web上发布。页面JavaScript URL会相应更改,但是现在在浏览器中打开会返回控制台错误Cross-Origin Request Blockedhttp://mydomain.com/hello/fetch()http://localhost:8888/

为了安全起见,浏览器仅允许客户端XMLHttpRequestFetch API调用访问托管页面的同一域。

幸运的是,跨域资源共享(CORS)使我们能够规避该安全限制。设置HTTP响应标头可告知浏览器允许该请求。可以将其设置为特定域或所有域(由上述Joke API完成)。Access-Control-Allow-Origin*

因此,可以更改Web服务API代码以允许从任何域上运行的任何客户端脚本进行访问:

// /hello/ GET request
app.get('/hello/:name?', (req, res) =>
  res
    .append('Access-Control-Allow-Origin', '*')
    .json(
      { message: `Hello ${req.params.name || 'world'}!` }
    )
);

另外,Express.js中间件函数可以将标头附加到每个端点请求:

// enable CORS
app.use((req, res, next) => {
  res.append('Access-Control-Allow-Origin', '*');
  next();
});

// /hello/ GET request
// ...

REST挑战

REST的成功很大程度上归功于其简单性。开发人员可以随意实现自己喜欢的RESTful API,但这可能会带来更多挑战。

端点共识

考虑以下端点:

  • /user/123
  • /user/id/123
  • /user/?id=123

所有这些都是为user提取数据的有效选项123。当您进行更复杂的操作时,组合的数量会进一步增加。例如,返回十个姓氏以’A’开头的用户,并按生日按相反的生日顺序为第51条记录的companyX工作。

最终,格式化URL的形式无关紧要,但API的一致性很重要。对于许多开发人员而言,在大型代码库上很难做到这一点。

API版本控制

API的更改是不可避免的,但是当端点URL在内部和/或由第三方应用程序使用时,绝不应使它们无效。

通常对API进行版本控制以避免兼容性问题(例如,被取代),但是旧的端点仍处于活动状态。但是,由于维护了多个API,因此增加了工作量。较旧的API最终可能会被废弃,但是该过程需要仔细计划。/2.0/user/123/user/123

认证方式

上面显示的笑话API是开放的:任何系统都可以未经授权获取笑话。这对于访问私有数据或允许更新和删除请求的API不可行。

与RESTful API在同一域中的客户端应用程序将像其他任何HTTP请求一样发送和接收cookie。(请注意,在较旧的浏览器中,需要设置init选项。)因此,可以验证API请求,以确保用户已登录并具有适当的权限。Fetch()credentials

第三方应用程序必须使用其他授权方法。常见的身份验证选项包括:

  1. HTTP基本认证Authorization包含base64编码的username:password字符串的HTTP标头在请求标头中传递。
  2. API密钥。通过发布可能具有特定权限或限于特定域的密钥,可以授予第三方应用程序使用API​​的权限。密钥在HTTP标头或查询字符串中的每个请求中传递。
  3. OAuth。通过向OAuth服务器发送客户端ID和可能的客户端密码,可以在获得任何请求之前获取令牌。然后,随每个API请求一起发送OAuth令牌,直到其过期为止。
  4. JSON Web令牌(JWT)。数字签名的身份验证令牌在请求和响应标头中安全地传输。

API身份验证将根据使用上下文而有所不同。在某些情况下,例如,从地图API生成路线时,第三方应用程序被认为是具有特定权限的另一个登录用户。在其他情况下,第三方应用程序由注册用户使用,并且只能访问其数据-例如,在获取电子邮件内容或文档时。

安全

RESTful API提供了另一种访问和操作应用程序的途径。即使这不是一个有趣的黑客攻击目标,行为不端的客户端也可能每秒发送数千个请求,并使服务器崩溃。

安全性不在本文讨论范围之内,但是常见的最佳做法包括:

  • 使用HTTPS
  • 使用可靠的身份验证方法
  • 使用CORS将客户端调用限制为特定域
  • 提供最小的功能-也就是说,不要创建不需要的DELETE选项
  • 验证所有端点URL和主体数据
  • 避免在客户端JavaScript中公开API令牌
  • 阻止来自未知域或IP地址的访问
  • 阻止意外的大负载
  • 考虑速率限制-也就是说,使用相同API令牌或IP地址的请求限制为每分钟N个
  • 使用适当的HTTP状态代码缓存头进行响应
  • 记录请求并调查失败。

多个请求和不必要的数据

RESTful API受其实现限制。响应中包含的数据可能超出您的需要,或者需要其他请求才能访问所有数据。

考虑一个RESTful API,它提供对作者和书籍数据的访问。为了显示最畅销的10本图书的数据,客户将:

  1. 请求/book/按销售数量排序的前10个详细信息(最畅销的产品)。该响应包含具有每个作者ID的书籍列表。
  2. 最多提出10个请求以获取每个作者的姓名。/author/{id}

这被称为N + 1问题;必须为父请求中的每个结果发出N个API请求。

如果这是一个常见的用例,则可以更改RESTful API,以便每本返回的书都包含完整的作者详细信息,例如姓名,年龄,国家/地区,传记等。它还可以提供其他书籍的详细信息,尽管这会大大增加响应的负载!

为了避免大量响应,可以调整API,以便可以控制作者的详细信息(例如),但是选项的数量很快就会变得令人困惑。?author_details=basic

GraphQL可以修复REST吗?

这些REST难题使Facebook创建了GraphQL(一种Web服务查询语言)。可以将其视为Web服务的SQL。单个请求定义了您需要什么数据以及如何返回它们。

GraphQL解决了RESTful API带来的许多挑战。话虽如此,很少有公司遇到可与Facebook媲美的问题。一旦您的RESTful API的发展超出其简单的起点,就值得考虑GraphQL。

REST链接和开发工具

有许多工具可以帮助所有语言的RESTful API开发。值得注意的选项包括:

  • Swagger:各种工具,可帮助设计,记录,模拟,测试和监视REST API
  • 邮递员:RESTful API测试应用程序
  • Postwoman:Postman的开源,基于Web的替代方案。

还有许多公共REST API,可满足笑话,货币换算,地理编码,政府数据以及您能想到的每个主题。许多都是免费的,尽管有些要求您注册API密钥或使用其他身份验证方法。分类列表包括:

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/261877.html

(0)
上一篇 2022年5月25日
下一篇 2022年5月25日

相关推荐

发表回复

登录后才能评论