理解并使用REST API


这是一篇学习笔记,原文在最后的总结里。
我按照自己的理解用中文总结了一遍,更新了原文中不能用的服务,并添加了一些自己的使用情景。

什么是REST API

  • API (application programming interface): server与client之间交流的接口
  • REST (Representational State Transfer): 创建API时的一些规则。比如访问某个特定URL的时候,能得到数据

每个URL叫作一个request,返回的数据叫作response。

Request的构成

  1. The endpoint
  2. The method
  3. The headers
  4. The data (or body)

The Endpoint

endpoint就是我们访问的url,有两部分组成。root-endpoint是API的根,path决定了我们想要的数据资源。拿GitHub来举例。

https://api.github.com/users/zellwk/repos

其中https://api.github.com是root-endpoint,path是/users/zellwk/repos

想要知道什么path对我们有用的话,需要去看API文档。比如GitHub的API docs告诉我们下面的path:

/users/:username/repos

path中出现引号(:)的地方是变量,需要我们传入自己需要的值。比如下面的endpoint可以列出我的所有repos:

https://api.github.com/users/bramblexu/repos

用cURL来测试endpoint

cURL是一个命令行工具,大部分API文档都会提供cURL的写法。

# 检查是否安装
curl --version

# 测试github root endpoint
curl https://api.github.com

# 获取我的所有repo信息
curl https://api.github.com/users/bramblexu/repos

# 按照push的时间排序后返回
curl https://api.github.com/users/bramblexu/repos\?sort\=pushed

上面第四种使用查询参数的方法必须要要使用反斜线(\)来转义,因为 ?= 都是命令行里的特殊符号。

JSON

JOSN是一种数据格式,request发送的请求和reponse返回的结果都是以JOSN格式表现的。相当于Python里的字典类型。

{
  "property1": "value1",
  "property2": "value2",
  "property3": "value3"
}

The Method

在对server访问的时候,通过method来指定request的类型。有下面5种

  • GET
  • POST
  • PUT
  • PATCH
  • DELETE

主要用于执行4种操作: Create, Read, Update and Delete (CRUD).

Method Name Request Meaning
GET This request is used to get a resource from a server. If you perform a GET request, the server looks for the data you requested and sends it back to you. In other words, a GET request performs a READ operation. This is the default request method.
POST This request is used to create a new resource on a server. If you perform a POST request, the server creates a new entry in the database and tells you whether the creation is successful. In other words, a POST request performs an CREATE operation.
PUT and PATCH These two requests are used to update a resource on a server. If you perform a PUT or PATCH request, the server updates an entry in the database and tells you whether the update is successful. In other words, a PUT or PATCH request performs an UPDATE operation.
DELETE This request is used to delete a resource from a server. If you perform a DELETE request, the server deletes an entry in the database and tells you whether the deletion is successful. In other words, a DELETE request performs a DELETE operation.

API文档其实已经告诉我们该用哪个method了。比如想要获得一个用户在GitHub上的所有repo,文档告诉我们应该使用 GET request:

GET /users/:username/repos

想要创建一个新repo的话,要使用 POST request:

POST /user/repos

我们也可以在curl里指定request method,只要把method放在 -X--request 之后即可

curl -X POST https://api.github.com/user/repos

但是上面的命令会显示失败:

{
  "message": "Requires authentication",
  "documentation_url": "https://developer.github.com/v3"
}

这是因为我们必须要获得验证(authentication)才行。关于验证之后会介绍。

The Headers

介绍完了endpoint,method,接下来介绍headers。

Header的作用是给client和server提供信息。用途很广泛,比如提供验证,这里 HTTP Headers Reference 给出了很多有效的header。

HTTP header的格式是属性-值对(property-value pair),中间用冒号隔开。比如下面:

"Content-Type: application/json"

使用curl的时候,通过 -H--header 来指定header。比如下面的事例

curl -H "Content-Type: application/json" https://api.github.com

"Content-Type: application/json" 的意思是指定request body的data格式为JSON。对于GitHub来说,不指定类型也可以,这里只用作讲解header的例子。

想要查看hearder信息的话,可以添加 -v--verbose 选项。

curl -H "Content-Type: application/json" https://api.github.com -v

下面是返回的结果,主要分为4部分:

  • * 的部分是cURL提供的额外信息
  • > 是 request headers
  • < 是 response headers
  • 最后{}里的部分就是返回的json数据
* Rebuilt URL to: https://api.github.com/
*   Trying 52.69.239.207...
......
*  SSL certificate verify ok.


> GET / HTTP/1.1
> Host: api.github.com
......
> Content-Type: application/json


< HTTP/1.1 200 OK
< Date: Wed, 04 Dec 2019 00:21:53 GMT
......
< X-GitHub-Request-Id: 8148:28BC:476784:585465:5DE6FC20


{
  "current_user_url": "https://api.github.com/user",
  "current_user_authorizations_html_url": "https://github.com/settings/connections/applications{/client_id}",
  ......
}

The Data (Or “Body”)

介绍完了endpoint,method,headers,最后介绍Data(“body” or “message”)。data包含我们想要发送给server的信息。只能使用 POST, PUT, PATCH or DELETE requests。

在curl里指定 -d--data 选项来添加data:

# 一个数据字段
curl -X POST <URL> -d property1=value1

# 两个数据字段
curl -X POST <URL> -d property1=value1 -d property2=value2

# 使用\分为多行
curl -X POST <URL> \
  -d property1=value1 \
  -d property2=value2

当我们已经建好自己的后端,并准备好了数据的时候。我们通常想要知道client会发送什么样的数据给后端提供的API接口。作者这里介绍了两种方法来测试来自client的HTTP request。一种是自己建server,具体方法见this article (learn to create a server with Node, Express, and MongoDB)。另一种方法是利用Requestbin

点击Create a RequestBin,可以得到一个endpoint。比如我得到的是https://requestbin.io/werg85we (这个endpoint会在48小时后失效)。我们就可以测试一下POST方法。在命令行执行下面的命令:

curl -X POST https://requestbin.io/werg85we \
  -d property1=value1 \
  -d property2=value2

然后刷新一下网页,就能看到我们的POST request的结果了。左边的FORM/POST PARAMETERSRAW BODY显示了我们传入的data。

curl默认是以 表格字段 (form field) 来传送数据的。如果我们想要json,可以指定 Content-Typeapplication/json。写成下面这样:

curl -X POST https://requestbin.io/s5bpdms5 \
  -H "Content-Type: application/json" \
  -d '{
  "property1":"value1",
  "property2":"value2"
}'

header里的Content-Type变成了application/json,可以看到左下角的部分也变成json格式了:

关于如何正确传入json数据,可以参考我的另一篇文章:如何正确传递含有变量的json数据给curl

其他一些知识点

验证 (Authentication)

之前我们在The Method这一节提到过使用POST的话,会返回错误信息,提示我们要进行验证。因为 POST, PUT, PATCH, DELETE 这些操作都是要更改数据库的,所以要通过验证确保用户有更改数据库的权限。而 GET 也需要验证则是因为每个用户有一些隐私的部分是需要验证才能查看的(比如银行账户的余额)。

有两种方法可以验证:

  1. 使用用户名和密码(也叫做基本验证,basic authentication)
  2. 使用 秘密令牌(secret token)

使用token的方法包括 oAuth,也就是说通过其他一些有名的SNS服务来验证身份,比如GitHub、Google等等。

Basic Authentication(基本验证)

基本验证指的是 用户名和密码。如果对OAUTH感兴趣的话,可以看这篇文章,“What You Need To Know About OAuth2 And Logging In With Facebook” by Zack Grossbart

在curl上使用基本验证也很简单,通过 -u 选项传入用户名和密码即可。

curl -X POST -u "username:password" https://api.github.com/user/repos

提示由原先的"message": "Requires authentication" 变成 "message": "Problems parsing JSON" ,这个说明我们验证成功了,只不过因为我们使用了POST request,但是却没有提供data,所以才会提示说Problems parsing JSON

secret token(秘密令牌)

关于GitHub token的验证,其实也可以用上面的方式来完成。因为我开启了GitHub MFA(二段验证),所以无法通过输入密码来访问我的仓库。关于这部分的解释,我在另一篇利用GitHub API爬取个人活动的文章里有介绍,Build a Python Crawler to Get Activity Stream with GitHub API

对于这种情况,就必须使用token了。通过官网的教程创建personal access token,然后把上面password的部分改成token就可以了。

curl -X POST -u "username:token" https://api.github.com/user/repos

提示显示 "message": "Problems parsing JSON" ,说明我们验证成功。只不过因为我们使用了POST request,但是却没有提供data,所以才会提示说Problems parsing JSON

HTTP状态代码和错误消息

根据状态码可以知道response的状态,下面是号码的规则:

  1. 200+ means the request has succeeded.
  2. 300+ means the request is redirected to another URL
  3. 400+ means an error that originates from the client has occurred
  4. 500+ means an error that originates from the server has occurred

我们可以添加verbose option (-v or --verbose) 或 head option (-I or --head),只输出一些重要信息,通过查看状态码,判断response是否成功。

curl -X POST https://api.github.com/user/repos -i

# 下面是返回的结果
HTTP/1.1 401 Unauthorized
Date: Wed, 04 Dec 2019 01:22:22 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 115
Server: GitHub.com
Status: 401 Unauthorized
......

关于状态码可以查看MDN’s HTTP Status Reference

API Versions

工程师会更新APIs,所以我们最好指定使用的API版本,防止API更新之后,我们的访问会失效。

指定API版本的方式有两种,具体看API是如何指定的。

  1. Directly in the endpoint
  2. In a request header

Twitter是第一种,在endpoint里用1.1来指定版本:

https://api.twitter.com/1.1/account/settings.json

GitHub是第二种,在Accept header里指定version 3:

curl https://api.github.com -H Accept:application/vnd.github.v3+json

总结

这篇文章介绍了REST API及其用法,而且非常易懂,没有冗长的解释说明,提供了很多例子。感兴趣的可以去看一下原文。

欢迎订阅我的博客:RSS feed
知乎: 赤乐君
Blog: BrambleXu
GitHub: BrambleXu
Medium: BrambleXu


文章作者: BrambleXu
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 BrambleXu !
评论
  目录