第一个模块结束时,你创建了一个HTTP请求,发送了它,并得到了一个响应。

我们在未来还会做很多次。我们将向第三方服务器发送请求。我们将制作应用程序,使其本身接受此类请求并返回一个响应。我们将创建复杂的逻辑来处理请求。

因此,最好是彻底研究与这些请求有关的一切,详细分析它们。这样,你就不能只是把请求复制到某个地方并重复它,而是真正弄清楚这一切是如何运作的。

这就是我们在第二个模块中要做的。我们开始吧!

让我们从理论开始。


学习REST API

REST API基础知识

如果你在第一个模块中做了功课,研究了文档,你应该注意到了API这个首字母缩写。实际上,如果开发者想了解与网络上的一些服务或应用程序的交互,首先应该研究的就是API文档。

API - 应用程序编程接口。这 是对客户端和服务器之间相互通信方式的描述。我们打开API文档,从那里学习如何从服务器上获得必要的数据。

我们总是希望这种互动是简单的、可理解的。这对开发者(在设计一个新的服务时不需要重新发明轮子)和用户(如果一个服务的工作原理与以前熟悉的服务相同,那么它就更容易学习)来说都简化了任务。在这里,值得一提的是一个新的术语--REST。

REST--是Representational State Transfer的首字母缩写。这听起来可能不是很清楚,但简单地说,REST是一种客户端和服务器之间的互动(信息交换)方式。

这不是一些僵化的规则和要求。REST并不强迫使用任何特定的编程语言,也不以严格的准则束缚双手。REST被称为一种架构风格,它定义了一个系统架构必须遵守的6个原则。

因此,考虑到REST的原则而开发的API被称为REST API,而应用程序本身被称为RESTful

我们将创建这样的RESTful应用程序,所以值得马上讨论它们所要遵守的原则。

  1. 客户端-服务器模式。该原则定义了客户和服务器的分离,以及他们需求的区分。客户端不必担心数据是如何存储的,最主要的是它在请求时被发布。反过来,服务器也不关心客户将如何处理这些数据,如何进一步处理和显示这些数据。这使得他们可以相互独立发展,并提高了系统的可扩展性。
  2. 无状态性。这个原则意味着服务器不应该根据以前对这个客户的经验 "想出 "响应。任何请求都是以包含其处理的所有必要信息的方式提出的,而不考虑以前的请求。
  3. 缓存。 为了尽量减少传输的数据,有一个缓存机制。例如,如果在某些页面上显示一个标志,那么每次都从服务器上请求它是没有意义的。它并不经常变化,只需获取一次并将其保存在客户端的计算机上,放在缓存中即可。但如果我们需要得到汽车当前速度的信息,那么缓存就没有任何帮助了。这个原则决定了由服务器传输的数据应该被指定为可缓存或不可缓存。
  4. 统一的接口。该 原则定义了客户-服务器交互的单一格式。所有请求的结构必须是相同的。数据必须以相同的形式发送,无论谁来请求它。
  5. 分层系统。客 户端和服务器不一定直接交流。数据传输可以通过几个中间节点。在这种情况下,系统的设计使客户和服务器都不知道他们是在与最终的应用程序还是中间节点进行交互。这允许你平衡服务器上的负载,增加可扩展性。
  6. 按需编写代码 (可选)唯一不是强制性的原则。根据它,客户端可以通过从服务器下载可执行代码(例如,脚本)来扩展其功能。在这种情况下,代码应该只在需求时执行。

不是太多理论吗?

让我们把它付诸实践。

创建一个API请求

让我们打开AppMaster,用它创建一个API请求,并更好地了解这个请求是如何工作的。


API请求是在 "业务逻辑 "部分的 "外部API请求 "标签中创建的。

是时候点击 "+新API请求 "了。


名称和描述可以设置为任何内容,它们只供我们个人使用。

让我们来处理真正重要的数据。

创建一个请求的最低要求是指定其方法和地址(URL)。让我们从最后一项开始。


URL- 统一资源定位器。给予互联网上特定资源的一个地址。这种资源最熟悉的版本是一个HTML页面--我们在浏览器的地址栏中输入其URL,然后打开所需的网站。同时,资源本身可以是任何东西,一张图片、一段视频、一个数据集。最主要的是,这个资源有一个特定的指针--一个URL,你可以向其发送请求以获得这个资源。

参考其地址上的数据,我们还指出请求的方法(你也可以说是类型),也就是说,我们指出实际上需要对这个数据做什么。

当我们为第一个模块的任务发送请求时,我们收到了数据。这就是GET方法。这种方法是最明显的方法,也是唯一需要的方法。因此,即使我们没有明确指定它,仍然默认为这是GET。

让我们来看看还有哪些方法存在。


HTTP标准本身并没有限制可以使用的方法的数量。同时,为了保持兼容性,只有一些最标准的方法仍然被使用。在AppMaster的API请求中,有5种不同的方法可以使用。

  • 获取。已经处理好了。该方法请求提供一个资源,并接收数据。
  • POST。要从某个地方获取数据,你首先需要把这些数据放在那里。POST方法就是这样做的。向服务器发送数据,创建一个资源。
  • PUT。与POST方法类似,但它的工作是更新数据。它不创建新的数据,而是替换现有的数据,更新它。
  • DELETE。顾名思义,它删除数据。
  • PATCH。该方法类似于PUT,但用于部分更新数据,而不是完全替换它。例如,使用PATCH方法,你可以改变一篇文章的标题,或者改变一些参数的值。

重要的是要考虑到这样一个事实:服务器根本不需要完全按照方法中指定的内容来做。我们可以用DELETE方法发送某个页面的地址,但这并不意味着服务器会真的删除它。但是,纯粹从理论上讲,他可以用GET命令来做这件事。或者不改变任何东西,但同时在响应POST的时候发送数据。只是因为开发者是这样配置的。

这就是REST发挥作用的地方,它说是时候同意遵守命令了,停止混乱,完全按照方法中的指示去做。至少,这应该是主要任务(尽管不一定是唯一的任务)。例如,当使用GET方法传输一篇文章的内容时,你可以同时将其浏览次数的计数器增加1。

所以,我们弄清楚了数据的位置以及可以用它做什么。让我们更进一步,让我们看看这个请求还能有哪些组件。


URL参数。有些情况下,我们只知道URL的一部分。一个例子是Appmaster.io网站上的文章。所有文章的起始地址都是一样的 - https://appmaster.io/en/blog/。但是,每篇文章都有自己的标题,相应地,它有自己的独立部分,以准确地表明这篇特定的文章。

在这种情况下,要使用URL Params。我们立即规定一般的部分,而将其余部分留待过程中决定。因此,URL被写成这样的形式:https://appmaster.io/ru/blog/:id/

已知部分按原样写,变量部分放在": "符号之后。这个变量部分的名称(已经没有":")被添加到参数列表中。在这种情况下,可以有几个变量部分,其位置在URL的任何地方。


查询参数。还记得我们在第一个模块中向boredapi.com发送了一个请求吗?除了地址之外,还规定了额外的数据。那就是查询参数(Query Params)。

它们写在URL后面,用一个"?"符号与之分开。参数的名称、符号"="和参数本身的值都有说明。如果同时使用几个参数,它们会被"&"号分开。

然而,在AppMaster中指定参数时,你不需要考虑请求规则。所有的东西都会被自动正确格式化。你只需要指定参数本身的名称并将其添加到列表中。

当数据源是相同的,但数据本身可能是不同的,就会使用查询参数。例如,Boredapi包含了一个巨大的列表,其中有很多事情要做。但我们只对那些为一个人准备的感兴趣,这就是我们在请求参数中所表示的。

另一个选项是一个访问密钥。你可能已经在模块1中提到Alphavantage时使用了这个选项。只有在注册和发送请求参数中的个人密钥后,才能获得数据。

请注意你在互联网上访问的网页,你可能也会在其中发现各种参数。例如,打开Ventusky.com的天气页面,在查询参数中会发送经纬度的地理值。

头信息。请求头信息。通常头文件包含关于请求的服务信息(元信息)。头信息允许服务器获得更多关于请求数据的客户端的信息。标头可以包含关于使用哪种浏览器的信息,期望响应采用什么编码,用什么语言,请求的确切时间,等等。在访问受保护数据的情况下,头文件可能包含一个授权密钥。

在大多数情况下,头文件是可选的。甚至在第一个模块中,我们已经提出了一个没有指定任何头信息的请求(尽管这并不意味着该请求实际上是在没有头信息的情况下发送的)。

头部。请求主体。GET请求通常不需要它,但如果我们想向服务器发送一些数据,发送POST或PUT请求,那么这些数据将被放在请求正文中。同时,你可以在请求体中放置任何复杂的数据,例如,发送一个视频文件,而不局限于一些数字或一个文本字符串。

来自服务器的Response几乎是按照同样的方案工作的。由于显而易见的原因,它没有请求参数,但头信息和正文都包含在响应中(尽管它们可能是空的)。

一个重要的区别是响应的状态。

状态代码。它出现在服务器响应的第一行。状态是一个三位数的数字(代码本身),后面是一个解释它的短语。

通过状态代码,你可以发现请求的结果,并了解接下来应该采取什么行动。

所有可能的状态代码被分为5类。代码的第一个数字决定了是否属于一个特定的类别。让我们把它们分解一下。

1xx- 信息代码。报告请求的进展。在实际操作中,它们很少被使用。

2xx--成功代码。它们报告说一切正常,请求已成功完成。在响应GET请求时,我们通常期望收到一个200(OK)代码。一个成功的PUT请求会发送一个201(创建)代码。

3xx- 重定向。表示请求应该被发送到一个不同的地址。一个例子是代码301(Moved Permanently),表示所需的数据现在在一个新的地址(新地址本身在Location头中传递)。

4xx- 客户端错误代码。其中最著名的是404(未找到),报告说在指定的地址没有必要的数据。其他常见的情况。400(坏请求,请求中的语法错误),401(未经授权,访问需要认证),403(禁止,拒绝访问)。

5xx- 服务器错误代码。报告服务器方面的错误。作为一个例子。500(内部服务器错误,任何无法归结为已知代码的不可理解的错误),503(服务不可用,服务器由于技术原因暂时无法处理请求)

在这一点上,我们可以认为我们已经处理了理解REST API的基本信息以及HTTP请求和响应的结构。现在只剩下一点需要澄清--数据类型。如果你已经尝试在AppMaster中创建你的API请求,你可能注意到所有的数据(在参数中,在头文件中,在正文中)不仅要求你指定名称,而且还要求你指定数据类型。


对于人类来说,如何处理这些数据通常是非常明显的,因为有一定的背景。假设我们知道2+2=4。我们猜测这些是数字,加法的结果将是另一个数字。

但它可能不是数字,而是文本数据。那么它们相加的结果可能是字符串的连接,2+2会变成 "22"。在这里,为了使计算机不必考虑任何问题,有一个确切的数据类型指示。同时,其他任务也得到了解决。例如,提供保护以防止输入不正确的数据;最初,没有机会在用于输入电话号码的区域注册电子邮件地址。

有很多不同的数据类型,现在我们将考虑最基本的数据类型,在课程的后续模块中我们将熟悉其余的数据类型。

String- 字符串数据类型,没有特殊格式的纯文本。

Integer- 整数数据类型。可用于计数器或不需要小数的计算。

Float- 浮点数。它用于需要提高精度而整数值不够的地方。

这里可能会出现一个逻辑上的问题。为什么不总是使用Float,那为什么我们需要Integer?但更高的精度需要更多的资源。对于一些小的计算来说,这可能是完全看不到的,但是在大量数据的情况下,使用合理的数据类型可以大大降低对计算能力和磁盘空间的要求。

布尔- 布尔数据类型。最简单的数据类型。它取两个值中的一个,写成True或False。你经常可以看到以1(真)和0(假)的形式指定。


家庭作业

通过在AppMaster的外部API请求部分创建请求,重复作业中对第一个模块的请求。

  1. 创建一个请求给BoredAPI。从文档中指定至少5个不同的参数。提交几个不同的请求,只指定所需的参数。
  2. 给Alphavantage创建一个请求。使用这些参数来获取不同货币之间的汇率。