什么是REST API
假设您要在YouTube上查找有关蝙蝠侠的视频。您打开Youtube,在搜索字段中输入“蝙蝠侠”,然后按Enter,然后您会看到有关蝙蝠侠的视频列表。REST API的工作方式与此类似。您搜索某些内容,然后从请求的服务中获得结果列表。
一个API是应用程序编程接口。这是一组允许程序相互通信的规则。开发人员在服务器上创建API,并允许客户端与之对话。
REST确定API的外观。它代表“表现层状态转换”。这是开发人员创建API时要遵循的一组规则。这些规则之一规定,当您链接到特定的URL时,您应该能够获得一条数据(称为资源)。
每个URL称为请求,而发送回给您的数据称为响应。
对一个请求进行剖析(request)
了解一个请求的组成部分是非常重要的,它一般由四个部分组成:
- 终点 (endpoint)
- 方法 (method)
- 头部 (headers)
- 数据 (或者body)
一个endpoint(或者route) 是你请求的url。它遵守下面的结构:
root-endpoint/?
该 根终点(endpoint) 是你请求API的起点。GitHub的API 根终点(endpoint) 是https://api.github.com
而Twitter的API 根终点(endpoint) 是https://api.twitter.com
该路径确定您要请求的资源。可以将其想象为一台自动答录机,它要求您按1进行一项服务,按2进行另一项服务,按3进行另一项服务,依此类推。
您可以访问路径,就像可以链接到网站的各个部分一样。例如,要获取www.example.com下标记的所有帖子的列表,请导航至https://www.example.com/tag/javascript/
。https://www.example.com/
是根端点,/tag/javascript
是路径。
要了解可用的路径,您需要查看API文档。例如,假设您要通过Github的API获取某个用户的存储库列表。该文档告诉您使用以下路径进行操作:
/users/:username/repos
:
路径上的所有冒号()表示变量。您应将这些值替换为发送请求时的实际值。在这种情况下,您应该用:username
要搜索的用户的实际用户名替换。如果要搜索我的Github帐户,我将替换:username
为tony
。
在Github上获取我的仓库清单的端点是:
https://api.github.com/users/tony/repos
端点的最后一部分是查询参数。从技术上讲,查询参数不是REST体系结构的一部分,但是您会看到很多API使用它们。因此,为了帮助您完全理解如何阅读和使用API,我们还将讨论它们。查询参数使您可以选择使用键值对修改请求。它们始终以问号(?
)开头。然后,每个参数对都用&符号分隔&
,如下所示:
?query1=value1&query2=value2
当您尝试在Github上获取用户存储库的列表时,可以在请求中添加三个可能的参数以修改提供给您的结果:
如果要获取我最近推送到的存储库的列表,可以设置sort
为push
。
https://api.github.com/users/tony/repos?sort=pushed
使用Curl测试端点
您可以使用任何编程语言发送请求。JavaScript用户可以使用Fetch API和jQuery的Ajax方法之类的方法;Ruby用户可以使用Ruby的Net :: HTTP类,Python用户可以使用Python请求;等等。
在本文中,我们将使用名为cURL的命令行实用程序。我们使用cURL是因为API文档通常是参考cURL编写的。如果您了解如何使用cURL,那么理解API文档将没有问题。然后,您可以使用首选语言轻松执行请求。
在继续之前,您需要确保在计算机上安装了cURL。打开您的终端并输入curl -version
。此命令检查系统上已安装的cURL版本。
curl --version
如果您未安装cURL,则会收到“找不到命令”错误。如果出现此错误,则需要继续安装curl。
要使用cURL,请键入curl
,然后键入您要的终结点。例如,要获取Github的根端点,请键入以下内容:
curl https://api.github.com
要获得用户存储库的列表,您可以将端点修改为正确的路径,就像我们上面讨论的那样。要获取我的存储库列表,可以使用以下命令:
curl https://api.github.com/users/tony/repos
如果希望在cURL中包含查询参数,请确保\
在?
和=
字符之前加反斜杠()。这是因为?
和=
是命令行中的特殊字符。您需要\
在命令行之前使用它们,以将它们解释为普通字符:
curl https://api.github.com/users/tony/repos\?sort\=pushed
尝试使用任一命令并执行请求!对于Github的root-endpont,您将获得类似的响应(但数据更多)。
JSON格式
JSON(JavaScript对象表示法)是一种用于通过REST API发送和请求数据的通用格式。Github发送回给您的响应也被格式化为JSON。
JSON对象看起来像JavaScript对象。在JSON中,每个属性和值都必须用双引号引起来,如下所示:
{
"property1": "value1",
"property2": "value2",
"property3": "value3"
}
返回请求的剖析
您已经了解到,请求包含四个部分。
- 终点
- 方法
- 标头
- 数据(或正文)
让我们遍历构成请求的其余部分。
方法
该方法是您发送到服务器的请求的类型。您可以从以下五种类型中进行选择:
GET
POST
PUT
PATCH
DELETE
这些方法为您提出的请求提供了含义。它们被用来执行四种可能的动作:Create
,Read
,Update
和Delete
(CRUD)。
方法名称 | 请求含义 |
---|---|
GET | 该请求用于从服务器获取资源。如果执行“ GET”请求,服务器将查找您请求的数据并将其发送回给您。换句话说,“ GET”请求执行“ READ”操作。这是默认的请求方法。 |
POST | 该请求用于在服务器上创建新资源。如果执行“ POST”请求,服务器将在数据库中创建一个新条目,并告诉您创建是否成功。换句话说,“ POST”请求执行“ CREATE”操作。 |
PUT 和PATCH | 这两个请求用于更新服务器上的资源。如果执行“ PUT”或“ PATCH”请求,则服务器会更新数据库中的条目,并告诉您更新是否成功。换句话说,“ PUT”或“ PATCH”请求执行“ UPDATE”操作。 |
DELETE | 此请求用于从服务器删除资源。如果执行“ DELETE”请求,服务器将删除数据库中的一个条目,并告诉您删除是否成功。换句话说,“删除”请求执行“删除”操作。 |
API使您知道使用每个请求的请求方法。例如,要获取用户存储库的列表,您需要一个GET
请求:
需要GET请求才能从用户那里获得存储库列表。要创建一个新的Github存储库,您需要一个POST
请求:
您可以在cURL中通过编写-X
或--request
,后跟请求方法来设置请求方法。下面的命令尝试通过cURL创建存储库:
curl -X POST https://api.github.com/user/repos
尝试运行此请求。您将得到一个响应,告知您需要身份验证。(稍后会详细介绍身份验证)。
{
"message": "Requires authentication",
"documentation_url": "https://developer.github.com/v3"
}
标头
标头用于向客户端和服务器提供信息。它可以用于许多目的,例如身份验证和提供有关身体内容的信息。您可以在MDN的HTTP标头参考中找到有效标头的列表。
HTTP标头是由冒号分隔的属性值对。下面的示例显示了一个标头,告诉服务器期望JSON内容。
"Content-Type: application/json". Missing the opening ".
您可以通过-H
或--header
选项发送带有curl的HTTP标头。要将上述标头发送到Github的API,请使用以下命令:
curl -H "Content-Type: application/json" https://api.github.com
(注意:Content-Type标头不是Github API起作用的必要条件。这只是一个示例,说明了如何在cURL中使用标头)。
要查看已发送的标头,可以在发送请求时使用-v
or --verbose
选项,如下所示:
curl -H "Content-Type: application/json" https://api.github.com -v
数据
数据(有时称为“正文”或“消息”)包含要发送到服务器的信息。此选项仅使用POST
,PUT
,PATCH
或DELETE
请求。
要通过cURL发送数据,可以使用-d
或--data
选项:
curl -X POST <URL> -d property1=value1
要发送多个数据字段,您可以创建多个-d
选项:
curl -X POST <URL> -d property1=value1 -d property2=value2
如果有道理,您可以将请求分成多行\
以使其更易于阅读:
curl -X POST <URL> \
-d property1=value1 \
-d property2=value2
如果您知道如何启动服务器,则可以制作一个API并测试您自己的数据。如果您不知道但有足够的勇气尝试,可以按照本文学习如何使用Node,Express和MongoDB创建服务器
如果您不想启动服务器,则可以转到Requestbin.com(免费!),然后单击“创建端点(endpoint)”。您将获得一个可用于测试请求的URL,https://requestb.in/1ix963n1
如下图所示。
如果要测试您的请求,请确保创建自己的请求容器。请求箱在创建后仅保持48小时处于打开状态。
现在,尝试将一些数据发送到您的请求bin,然后刷新您bin的网页。您会看到一些数据,如下所示:
curl -X POST https://requestb.in/1ix963n1 \
-d property1=value1 \
-d property2=value2
默认情况下,cURL发送数据就像通过页面上的“表单字段”发送数据一样。如果您希望发送JSON数据,则需要将设置Content-Type
为application/json
,并且需要将数据格式化为JSON对象,如下所示:
curl -X POST https://requestb.in/1ix963n1 \
-H "Content-Type: application/json" \
-d '{
"property1":"value1",
"property2":"value2"
}'
这就是(几乎!)您需要了解的有关请求结构的所有信息。
现在,还记得当您尝试POST
通过Github的API 发送请求时,收到一条消息,提示“需要身份验证”吗?好吧,这是因为您无权执行POST
请求!
认证方式
未经您的允许,您将不允许任何人访问您的银行帐户,对吗?按照相同的思路,开发人员可以采取措施来确保您只有在获得授权后才能执行操作。这样可以防止其他人冒充您。
因为POST
,PUT
,PATCH
并DELETE
要求修改数据库,开发者几乎总是把他们的认证墙后面。在某些情况下,GET
请求还需要认证(例如,当您访问银行帐户以检查当前余额时)。
在网络上,有两种主要的身份验证方法:
- 使用用户名和密码(也称为基本身份验证)
- 带有秘密令牌
秘密令牌方法包括oAuth,它使您可以通过Github,Google,Twitter,Facebook等社交媒体网络对自己进行身份验证。
要使用cURL执行基本身份验证,可以使用-u
选项,后跟用户名和密码,如下所示:
curl -x POST -u "username:password" https://api.github.com/user/repos
尝试在上述请求中使用您的用户名和密码对自己进行身份验证。身份验证成功后,您将看到响应从“需要身份验证”更改为“问题解析JSON”。
这是因为你还没有提供(这是所有所需的任何数据POST
,PUT
,PATCH
和DELETE
请求)到服务器。
利用到目前为止所学的知识,您应该能够通过cURL编辑上面的代码以创建Github存储库。现在,让我们谈谈HTTP状态代码和错误消息。
HTTP状态代码和错误消息
您之前收到的某些消息,例如“需要身份验证”和“解析JSON问题”,都是错误消息。它们仅在您的请求有问题时出现。HTTP状态代码可让您快速告知响应状态。范围从100+到500+。通常,数字遵循以下规则:
- 200+表示请求已成功。
- 300+表示请求已重定向到另一个URL
- 400+是指来自客户端错误已经发生
- 500+指来自服务器错误已经发生
您可以使用verbose选项(-v
或--verbose
)或head选项(-I
或--head
)调试响应的状态。
例如,如果您尝试-I
在POST
不提供用户名和密码的情况下添加到请求中,则会获得401状态码(未经授权):
如果您的请求因数据错误或丢失而无效,则通常会收到400状态代码(错误请求)。
要获取有关特定HTTP状态代码的更多信息,您可能需要查阅MDN的HTTP状态参考。
API版本
开发人员会不时更新其API。有时,API可能会发生很大变化,以至于开发人员决定将其API升级到另一个版本。如果发生这种情况,并且您的应用程序中断了,通常是因为您为较旧的API编写了代码,但是您的请求指向了较新的API。
您可以通过两种方式请求特定的API版本。选择哪种方式取决于API的编写方式。
这两种方式是:
- 直接在端点(endpoint)
- 在请求标头(headers)中
例如,Twitter使用第一种方法。Twitter的API的版本为1.1,通过其端点(endpoint)显而易见:
https://api.twitter.com/1.1/account/settings.json
另一方面,Github使用第二种方法。Github的API为版本3,您可以使用Accept
标头指定版本: