• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

HTTP和REST初学者指南

超文本传输协议 (HTTP) 是网络的生命。每次传输文档或提出ajax请求时都会使用它。但令人惊讶的是,HTTP 在一些 Web 开发人员中相对未知。

本介绍将演示一组称为 rest 的设计原则如何支持 HTTP。您将学习如何通过构建界面来充分发挥其强大功能,这些界面几乎可以在任何设备或操作系统中使用。

Envato Market 还拥有数千个有用的代码脚本、插件和应用程序来帮助您进行 Web 开发,例如Premium URL Shortener,这是一个 php 脚本,您可以将其安装在您的服务器上以创建自定义的缩短 URL。

HTTP和REST初学者指南  第1张

为什么是 REST?

REST 是一种组织独立系统之间交互的简单方法。自 2005 年以来,它越来越受欢迎,它激发了 Twitter api 等服务的设计。这是因为 REST 允许您以最小的开销与手机和其他网站等各种客户端进行交互。理论上,REST 与 Web 无关,但它几乎总是这样实现,并且受到 HTTP 的启发。因此,可以在 HTTP 可以使用的任何地方使用 REST。

另一种方法是在 HTTP 之上构建相对复杂的约定。通常,这会形成全新的语言。最杰出的例子是SOAPgraphql您必须学习一套全新的约定,但您永远不会充分利用 HTTP。因为 REST 受到 HTTP 的启发并发挥其优势,所以它是了解 HTTP 工作原理的最佳方式。

在初步概述之后,我们将检查每个 HTTP 构建块:URL、HTTP 动词和响应代码。我们还将回顾如何以 RESTful 方式使用它们。在此过程中,我们将通过一个示例应用程序来说明该理论,该示例应用程序模拟了通过 Web 界面跟踪与公司客户相关的数据的过程。

HTTP

HTTP 是允许在 Web 上来回发送文档的协议。协议是一组规则,用于确定可以交换哪些消息,以及哪些消息是对其他人的适当回复。另一个常见的协议是 POP3,您可以使用它来获取硬盘上的电子邮件。

在 HTTP 中,有两种不同的角色:服务器和客户端。一般来说,客户端总是发起对话;服务器回复。HTTP 是基于文本的;也就是说,消息本质上是文本位,尽管消息正文也可以包含其他媒体。文本使用使监控 HTTP 交换变得容易。

HTTP 消息由标头和正文组成。身体常常是空的;它包含您要通过网络传输的数据,以便根据标题中的说明使用它。标头包含元数据,例如编码信息;但是,在请求的情况下,它还包含重要的 HTTP 方法。在 REST 风格中,您会发现标头数据通常比正文更重要。

在工作中监视 HTTP

如果您使用 chrome 或 Firefox 开发人员工具,请单击顶部栏上的网络以查看您当前所在网站中的 HTTP 请求。您可能必须在打开网络开发人员工具的情况下刷新页面才能查看日志。例如:

HTTP和REST初学者指南  第2张

另一个熟悉 HTTP 的有用方法是使用专用客户端,例如 curlcURL 是一个 命令行工具,可在所有主要操作系统上使用。

安装 cURL 后,键入:

curl -v google.com

这将显示完整的 HTTP 对话。请求以 开头>,而响应以 开头<

网址

URL 是您识别要操作的事物的方式。我们说每个 URL 标识一个资源。这些是分配给网页的完全相同的 URL。实际上,网页是一种资源。

让我们举一个更奇特的例子,考虑我们的示例应用程序,它管理公司客户的列表。/clients将识别所有客户,同时/clients/jim将识别名为“Jim”的客户,假设他是唯一具有该名称的客户。

在这些示例中,我们通常不会在 URL 中包含主机名,因为它与界面的组织方式无关。尽管如此,主机名对于确保资源标识符在整个网络中都是唯一的很重要。我们经常说您将资源请求发送主机。主机与资源路径分开包含在标头中,资源路径位于请求标头的顶部:

GET /clients/jim HTTP/1.1
Host: example.com

最好将资源视为名词。例如,以下不是 RESTful:

/clients/add

这是因为它使用 URL 来描述操作。这是区分 RESTful 和非 RESTful 系统的一个相当基本的点。

最后,URL 应该尽可能精确;唯一标识资源所需的一切都应该在 URL 中。您不需要在请求中包含标识资源的数据。这样,URL 就充当了应用程序处理的所有数据的完整映射。

但是你如何指定一个动作?例如,您如何说您想要创建而不是检索新的客户记录?这就是 HTTP 动词发挥作用的地方。

HTTP 动词

每个请求在请求标头中指定特定的 HTTP 动词或方法。这是请求标头中的第一个全大写单词。例如,GET / HTTP/1.1表示正在使用 GET 方法,而DELETE /clients/anne HTTP/1.1表示DELETE正在使用该方法。

HTTP 动词告诉服务器如何处理由 URL 标识的数据。请求可以选择在其正文中包含附加信息,这些信息可能是执行操作所需的,例如,您希望与资源一起存储的数据。-d您可以使用选项在 cURL 中提供此数据。

如果您曾经创建过 html 表单,那么您会熟悉两个最重要的 HTTP 动词:GETpost但是还有更多可用的 HTTP 动词。构建 RESTful API 最重要的是GETPOSTPUTDELETE也可以使用其他方法,例如HEADOPTIONS,但比较少见。如果您想了解所有其他 HTTP 方法,官方来源是IETF

得到

GET是最简单的 HTTP 请求方法类型——浏览器每次单击链接或在地址栏中键入 URL 时使用的方法。它指示服务器将 URL 标识的数据传输给客户端。数据不应该因为GET请求而在服务器端被修改。从这个意义上说,一个 GET请求是只读的,但是当然,一旦客户端接收到数据,它就可以自由地对它自己进行任何操作——例如,格式化它以供显示。

PUT您希望创建或更新由 URL 标识的资源时,将使用请求。例如,PUT /clients/robin可能会在服务器上创建一个名为 Robin 的客户端。您会注意到这REST完全与后端无关;请求中没有任何内容告诉服务器应该如何创建数据——只是应该创建。这使您可以在需要时轻松交换后端技术。PUT请求包含用于更新或创建正文中的资源的数据。-d在 cURL 中,您可以使用开关向请求中添加数据:

curl -v -X PUT -d "some text"

删除

DELETE应该执行相反的PUT当您要删除由请求的 URL 标识的资源时,应该使用它。

curl -v -X DELETE /clients/anne

这将删除与资源关联的所有数据,由 标识/clients/anne

邮政

POST当您希望在服务器上进行的处理应该被重复时使用,如果POST请求被重复(也就是说,它们不是幂等的;更多内容见下文)。此外,POST请求应将请求正文作为您发布到的 URL 的下级进行处理。

简单来说,POST /clients/不应该导致资源/clients/本身被修改,而是 URL/clients/例如,它可以将一个新客户端附加到列表中,id并由服务器生成:

/clients/some-unique-id

PUTrequests 很容易代替POSTrequests 使用,反之亦然。有些系统只使用一个,有些POST用于创建操作和PUT更新操作(因为对于 PUT请求,您总是提供完整的 URL),有些甚至POST用于更新和PUT创建。

通常,POST请求用于触发服务器上不符合Create/Update/Delete范式的操作,但这超出了REST在我们的示例中,我们将一直坚持下去PUT

分类 HTTP 方法

安全和不安全的方法

安全方法是那些从不修改资源的方法。上面列出的四种方法中唯一安全的方法是GET其他是不安全的,因为它们可能导致资源的修改。

幂等方法

无论请求重复多少次,这些方法都达到相同的结果:它们是GETPUTDELETE唯一的非幂等方法是POST.

PUT并且DELETE被认为是幂等的可能会令人惊讶,但这很容易解释。使用相同的主体重复一个PUT方法应该修改一个资源,使其保持与上一个PUT请求中描述的相同:什么都不会改变!同样,删除资源两次也没有意义。因此,无论 a  PUTorDELETE请求重复多少次,结果都应该与只执行一次相同。

请记住:最终决定使用某个 HTTP 方法时会发生什么的,是程序员。HTTP 实现本身没有任何东西会自动导致资源被创建、列出、删除或更新。您必须小心正确地应用 HTTP 协议并自己执行这些语义。

陈述

我们可以通过以下方式总结到目前为止我们所学到的:HTTP 客户端和 HTTP 服务器交换有关由 URL 标识的资源的信息。

我们说请求和响应包含资源的表示。通过表示,我们指的是某种格式的关于资源状态或该状态在未来应该如何的信息。标题和正文都是表示的一部分。

HTTP 标头包含元数据,由 HTTP 规范严格定义;它们只能包含纯文本,并且必须以某种方式格式化。

正文可以包含任何格式的数据,这就是 HTTP 真正发挥作用的地方。您知道您可以使用任何人类语言发送纯文本、图片、HTML 和 XML。通过请求元数据或不同的 URL,您可以选择同一资源的不同表示。例如,您可以将网页发送到浏览器并将JSON发送到应用程序。

HTTP 响应应指定正文的内容类型。这是在标题中的Content-Type 字段中完成的。例如:

Content-Type: application/json

为简单起见,我们的示例应用程序只来回发送 JSON,但应用程序的设计方式应使您可以轻松更改数据格式以针对不同的客户或用户偏好进行定制。

HTTP 客户端库

要试验不同的请求方法,您需要一个客户端,它允许您指定要使用的方法。不幸的是,HTML 表单不符合要求,因为它们只允许您发出 GET 和 POST 请求。在现实生活中,API 是通过单独的客户端应用程序或通过浏览器中的 javascript 以编程方式访问的。

这就是为什么除了服务器之外,还必须在您选择的编程语言中提供良好的 HTTP 客户端功能。

同样,一个非常流行的 HTTP 客户端库是 cURL。您已经熟悉了本教程前面的 cURL 命令。cURL 包括一个独立的命令行程序和一个可供各种编程语言使用的库。特别是,cURL 通常是 PHP 开发人员首选的 HTTP 客户端解决方案。其他语言,例如 python,提供更多的本地 HTTP 客户端库。

设置示例应用程序

现在我们将构建一个准系统示例应用程序。您可以按照相应部分并使用代码附件中的相应文件夹在 node.js 或 PHP 中构建示例应用程序。两个应用程序的工作方式相同。如果您不确定选择哪个,Node.js 可能是更好的选择,因为它现在更常用。

Node.js 和 Express

为了运行示例应用程序,您需要安装 Node.js。完成后,打开源代码附件中的node.jsnpm install目录并运行.

PHP

要运行示例应用程序,您需要安装 PHP 5 和具有某种机制的 Web 服务器来运行 PHP。当前版本必须至少为 5.2 版才能访问json_encode()json_decode()功能。

至于服务器,最常见的选择仍然是带有 Apache 的 Apache mod_php,但您可以自由使用任何您喜欢的替代方案。有一个示例 Apache 配置,其中包含可帮助您快速设置应用程序的重写规则。对任何以/clients/开头的 URL 的所有请求都必须路由到我们的server.php 文件。

在 Apache 中,您需要启用mod_rewrite 并将提供的mod_rewrite 配置放在 Apache 配置或.htacess 文件中的某个位置。这样,server.php 将响应来自服务器的所有请求。Nginx 或您决定使用的任何替代服务器都必须实现相同的目标。

示例应用程序的工作原理

Node.js 和 Express

如果您查看代码,您会看到一些不同的方法,例如app.getor app.put这些是不同的路线。每个路由都匹配特定的 URL 和 HTTP 方法。

app.get("/clients", (_, res) => {
    ...
});
app.get("/clients/:client", (req, res) => {
	...
});
app.put("/clients/:client", (req, res) => {
	...
});
app.delete("/clients/:client", (req, res) => {
	...
});

您可能已经:client在 URL 中注意到了。那是一个参数,这意味着该部分 URL 中的任何内容都将匹配该路由,并且该部分 URL 将作为参数传递。在路由处理函数内部,您可以看到描述逻辑的注释。最后,有app.listen.

app.listen(port, () => {
    console.log(`Example app listening on port ${port}`);
});

这将在 指定的端口启动服务器port回调函数在服务器启动后执行。

PHP

以 REST 方式处理请求有两个关键。第一个关键是根据 HTTP 方法启动不同的处理——即使 URL 相同。在 PHP 中,$_SERVER 全局数组中有一个变量,用于确定发出请求的方法:

$_SERVER['REQUEST_METHOD']

此变量包含字符串形式的方法名称,例如'GET''PUT'等。

另一个关键是知道请求了哪个 URL。为此,我们使用另一个标准 PHP 变量:

$_SERVER['REQUEST_URI']

此变量包含从第一个正斜杠开始的 URL。例如,如果主机名是example.com'https://example.com/'将返回'/',而'http://example.com/test/'将返回'/test/'

让我们首先尝试确定调用了哪个 URL。我们只考虑以 . 开头的 URL 'clients'其他都是无效的。

$resource = array_shift($paths);

if ($resource == 'clients') {
    $name = array_shift($paths);

    if (empty($name)) {
        $this->handle_base($method);
    } else {
        $this->handle_name($method, $name);
    }

} else {
    // We only handle resources under 'clients'
    header('HTTP/1.1 404 Not Found');
}

我们有两种可能的结果:

  • 资源是客户端,在这种情况下,我们返回一个完整的列表。

  • 还有一个标识符。

如果还有其他标识符,我们假设它是客户端的名称,并再次将其转发给不同的函数,具体取决于method我们使用一个 switch语句,在实际应用中应该避免这种情况:

switch($method) {
  case 'PUT':
      $this->create_contact($name);
      break;

  case 'DELETE':
      $this->delete_contact($name);
      break;

  case 'GET':
      $this->display_contact($name);
      break;

  default:
      header('HTTP/1.1 405 Method Not Allowed');
      header('Allow: GET, PUT, DELETE');
      break;
  }

响应代码

您可能已经注意到示例应用程序使用 PHP header(),将一些看起来很奇怪的字符串作为参数传递。header() 函数打印 HTTPheaders并确保它们的格式正确。标头应该是响应中的第一件事,因此在完成标头之前不应输出任何其他内容。有时,您的 HTTP 服务器可能配置为添加其他标头,除了您在代码中指定的标头。

标头包含各种元信息——例如,消息正文中使用的文本编码或正文内容的 MIME 类型。在这种情况下,我们明确指定 HTTP 响应代码。HTTP 响应代码标准化了一种通知客户端其请求结果的方式。默认情况下,PHP 返回一个200响应码,表示响应成功。

服务器应该返回最合适的 HTTP 响应码;这样,假设有任何错误,客户端可以尝试修复其错误。大多数人都熟悉常见的404 Not Found响应代码,但还有更多可用于适应各种情况的代码。

请记住,HTTP 响应代码的含义并不是非常精确;这是 HTTP 本身相当通用的结果。您应该尝试使用与当前情况最匹配的响应代码。话虽如此,如果您找不到完全合适的,请不要太担心。

以下是一些经常与 REST 一起使用的 HTTP 响应代码:

200 好

此响应代码表示请求成功。

201 已创建

这表示请求成功并创建了资源。它用于确认一个PUTPOST请求的成功。

400 错误请求

请求格式不正确。当数据未通过验证或格式错误时,POST尤其会发生这种情况。PUT

404 未找到

此响应表明找不到所需的资源。这通常会返回给所有指向没有相应资源的 URL 的请求。

401未经授权

此错误表示您需要在访问资源之前执行身份验证。

405 方法不允许

此资源不支持使用的 HTTP 方法。

409 冲突

这表明存在冲突。例如,您正在使用PUT请求创建相同的资源两次。

500内部服务器错误

当一切都失败了;通常,当服务器端出现意外情况导致处理失败时,使用 500 响应,从而导致服务器出错。

练习示例应用程序

让我们从简单地从应用程序中获取信息开始。我们想要客户端的详细信息,所以让我们向该资源的 URL'jim'发送一个简单的请求:GET

curl -v http://localhost:80/clients/jim

这将显示完整的邮件标题。响应中的最后一行将是消息正文;在这种情况下,它将是包含 Jim 的地址的 JSON(请记住,省略方法名称将导致GET请求;也替换localhost:80为您正在使用的服务器名称和端口)。

接下来,我们可以一次获取所有客户端的信息:

curl -v http://localhost:80/clients/

然后我们创建一个新客户端,命名为 Paul:

curl -v -X "PUT" http://localhost:80/clients/paul -d '{"address":"Sunset Boulevard" }' -H 'content-type: application/json'

现在您将收到一份包含 Paul 作为确认的所有客户的列表。

最后,删除客户端:

curl -v -X "DELETE" http://localhost:80/clients/anne

您会发现返回的 JSON 不再包含有关 Anne 的任何数据。

如果您尝试检索不存在的客户端,例如:

curl -v http://localhost:80/clients/jerry

您将获得 404 错误,而如果您尝试创建已存在的客户端:

curl -v -X "PUT" http://localhost:80/clients/anne

相反,您将收到 409 错误。

结论

重要的是要记住,HTTP 是为在系统之间进行通信而设计的,这些系统除了对协议的理解之外什么都不共享。通常,您在 HTTP 之外做出的假设越少越好:这允许最广泛的程序和设备访问您的 API。

我在本教程中使用了 PHP,因为它很可能是 Envato Tuts+ 读者最熟悉的语言。也就是说,虽然 PHP 是为 Web 设计的,但在以 REST 方式工作时可能不是最好的语言,因为它处理PUT请求的方式GETPOST.

文章目录
  • 为什么是 REST?
  • HTTP
  • 在工作中监视 HTTP
  • 网址
  • HTTP 动词
    • 得到
    • 删除
    • 邮政
  • 分类 HTTP 方法
      • 安全和不安全的方法
      • 幂等方法
  • 陈述
  • HTTP 客户端库
  • 设置示例应用程序
    • Node.js 和 Express
    • PHP
  • 示例应用程序的工作原理
    • Node.js 和 Express
    • PHP
  • 响应代码
    • 200 好
    • 201 已创建
    • 400 错误请求
    • 404 未找到
    • 401未经授权
    • 405 方法不允许
    • 409 冲突
    • 500内部服务器错误
  • 练习示例应用程序
  • 结论