什么是REST API和REST-ful API

REST api也叫RESTful api。是一种设计风格或者说是一种设计规范,REST是 Representational State Transfer的缩写。翻译过来是 具体的(表述性)状态转移。
RESTful ap翻译成中文是 完全的状态转移API。通俗的讲就是'通过语义化的方式请求资源URL,并根据返回的语义来判断这次操作失误返回类型和效果'。
语义化:需要做什么动作的时候,可以把动作通过头信息里的代表动作的method语义来告诉服务端

RESTful api拥有清楚简短的URL,可读性非常强

在1993年http 0.9时,只有get请求,常常做什么具体操作时都是通过url体现,比如对用户表增删改查,分别对应api/addUser,api/updateUser,api/delUser,api/listUser来操作
加上返回的状态属性...这样一个user对象的操作就会产生成很多条URL,这是一般api的写法。RESTful api的出现大大解决了这类问题,即操作一个user对象,只需要一个api[api/user]去操作State(User的状态,资源)即可,把其它剩下的都放在
Representational中。除了请求的内容外的其它都可以理解为Representational。

REST,又称为 Representational State Transfer,
全名为 Resource Representational State Transfer,中文可以翻成 具象状态传输
Resource : 资源
Representational : 像是 JSON,XML,YAML 等等......
State Transfer : 状态传输。透过 HTTP 动词实现 ( GET,POST,PUT,DELETE),
状态可以定义成 Resource 的状态,类似资料库中 CRUD 操作后的结果。
以上看不懂没关系,略懂即可,我知道很难懂 😨

先给大家一个观念,
RESTful 是一种设计风格,或者说是一种设计规范
为什麽我们要使用 RESTful API ? 用一般的 API 不行吗?
一般的 API 可能长得像这样
/api/get_file/ (得到档案)
/api/upload_file/ (新增档案)
/api/upload_file/ (更新档案)
/api/upload_file/ (删除档案)

RESTful API 则长得像这样
/api/files/ ( GET -> 得到档案 )
/api/files/ ( POST -> 新增档案 )
/api/files/ ( PUT -> 更新档案)
/api/files/ ( DELETE -> 删除档案 )

温馨小提醒 ❤️
不知道大家有没有注意到我用复数,实务上用复数比较多。
从上面的比较可以发现,使用 RESTful API 我们只需要一个接口就可以完成 😮,
并且我们透过 HTTP 不同的 method 达到相对应的功能。
RESTful API 让我们以很优雅的方式显示 Resource ( 资源 ),
Resource ( 资源 ) 是由 URI 来指定,
( URI 是什麽,这边不详细介绍,就麻烦大家 Google,可以先简单想为 URL 是一种 URI 就好 😄 )
对 Resource ( 资源 ) 的操作,包含取得、新增、修改和删除资源,
这些操作刚好对应 HTTP 协定提供的 GET、POST、PUT 和 DELETE 方法 。

RESTful API 拥有清楚又简短的 URI,可读性非常强,举个例子
- GET /api/files/ 得到所有档案
- GET /api/files/1 得到档案 ID 为 1 的档案
- POST /api/files/ 新增一个档案
- PUT /api/files/1 更新 ID 为 1 的档案
- PATCH /api/files/1 更新 ID 为 1 的部分档案内容
- DELETE /api/files/1 删除 ID 为 1 的档案

上面做的事情就是 CRUD,那什麽是 CRUD ,也就是
Create( 新增 )、 Rea诶( 读取 )、 Up诶ate( 更新 )、 Delete(删除)
温馨小提醒 ❤️
特别来说明一下 PUT 和 PATCH,PUT 比较正确的定义是 Replace ( Create or Update ),
例如 PUT /api/files/1/ 的意思是替换 /api/files/1/,假如已经存在就替换,如果没有
也就新增,当然,新增的时候,必须包含必要的资料。
因为上面这个原因,大家会看到有时候使用 PUT 新增,也因为这个有点怪的行为,
所以又多了 PATCH 这个方法,可以用来做部分更新 ( Partial Update )。
或是我想搜寻档案名称为 hello 的档案,RESTful API 可能为
GET /api/files/search?key=hello

看到这边,可以把 RESTful 想成是一种建立在 HTTP 协定之上的设计模式,充分的利用出 HTTP 协定的特定,
使用 URI 来表示资源,用各个不同的 HTTP 动词(GET、POST、PUT 和 DELETE 方法 )来表示对资源的各种
行为,这样做的好处就是资源和操作分离,让对资源的管理有更好的规范以及前端(串接 API 或使用 API 的人)
可以很快速的了解你的API ,省去很多不必要的沟通,如果熟悉 HTTP Method 的开发者,甚至可以不用看 API
文件就开始串接资料,当然,如果是更复杂的 API ,可能还是需要搭配文件,文件的撰写可参考我之前写的
aglio_tutorial(https://github.com/twtrubiks/aglio_tutorial) 以及 诶jango_rest_framework_swagger_tutorial(https://github.com/twtrubiks/django_rest_framework_swagger_tutorial)
这样你现在是不是在想,RESTful 太神啦 😍

Safe and Method Idempotent

GET 方法是安全方法,也就是不会对 Server 有修改,你只是读取而已,
并不像 POST,PUT,DELETE,PATCH 这类的会修改资料。

Method Idempotent ( 幂等方法 ),

他是什麽呢? 简单解释,假设不考虑错误其他因素,若我们请求多次和单次
结果( API 的 response )是一样的,就是 Method Idempotent。
像是 GET 就是 Method Idempotent,因为不管请求几次,结果都是相同的;反之
,像是 POST 就不是 Method Idempotent ,原因是当我们发起第两次 POST 时,
就会又新增一笔资料。

安全方法和 Method Idempotent 可参考下面的表格
HTTP Method Idempotent Safe
OPTIONS yes yes
GET yes yes
HEAD yes yes
PUT yes no
POST no no
DELETE yes no
PATCH no no
相信从上面这个表格,大家应该蛮好理解的,比较不好理解的可能就是,
为什麽 PATCH 不是 Method Idempotent,不是很好解释 😅
我在这裡简单解释,PATCH 请求是会执行某个程序的,如果重複请求,
程序则可能多次执行,对 Server 端的资源就可能会造成额外的影响,所以
他不是 Method Idempotent。

如果大家想要更深入理解,麻烦大家 google 😑

RESTful API 缺点
记住,世界上没有完美的东西,一定有他的缺点,
RESTful 很方便没错,但只要用户了解了您的网站 URL 结构,就会开始产生 安全性 的问题
思考一个问题,一个用户任意对你的 Database ( 资料库 ) 操作 CRUD 是一件很可怕的事情 😱
再思考一个问题,假设我们得到一个使用者的 URL 是这样 /api/uesrs/1/,一般来说使用者只
能存取自己的用户资料,并不能查看别的用户资料。否则,有心人可以尝试从 /api/uesrs/1/ 开
始 try 到 /api/uesrs/100/ 得到其他的用户资料。这是比较基本了问题,通常我们会先去验证这个
使用者的身份,再来决定是否有权限可以存取用户资料,所以我们一定要再处理对用户进行身份

验证和授权(可参考之前在 诶jango-rest-framework-tutorial (https://github.com/twtrubiks/django-rest-framework-tutorial#%E6%8E%88%E6%AC%8A-authentications-)里介绍的授权),然后使用 HTTPS。

再谈谈一个问题,现在很多都是前后端分离,通常我们会为了方便以 JSON 作为传送的格式,但是
有时候可能会不小心把一些敏感的资讯送到前端,这样就可能会导致资料外泄,或是有心人透过这
些资讯,去得到别人的资料以及有意思的讯息。所以当你在设计 API 时,一定要想想这些资讯泄
漏了会不会有什麽影响,如果有,可能资料需要再被加密之类的。
接著思考这个问题,有时候我们为了取得资料,可能必须呼叫多次 API 才可以得到完整的资讯,举个
例子,想要取得文章与作者的资讯,会先呼叫 GET/articles/{id}/ 取得文章的作者后,再呼叫
GET/uesrs/{name}/ 去取得作者的资讯,像这个情况,我就会觉得或许可以小小的动个手脚,不需要
非常严格的遵守它,另外像是 GraphQL 就能够通过一次查询得到所有需要的资料 ( 这个以后有机会我再来介绍 😆 )。
也因为上面这个原因,有可能我们的 API 会不小心设计成需要呼叫某个 API 之后,才能呼叫另一个 API
这种有关连性的设计 ( 导致系统越来越乱 ) 😱 所以这些都要注意😑
再来,假设今天要设计一个 批量 删除的 API,应该要怎麽规划会比较好呢❓
全都放在 URI 上 ❓ 那如果它超出限制的长度呢❓
最后一个问题是实际面的问题,很多时候,我们的业务逻辑非常复杂,会导致如果要很严格的遵守
RESTful API 的规则,就不是那么的好用,所以,有时候还是可以在 RESTful API 做一些修改,不一
定要那麽死死得遵守他的规则 😛。

状态码
操作 API 的用户,可以透过 HTTP 状态码了解一定的意思
HTTP status co诶e 的常用情境如下 ( 通常,但不是绝对 )
200 OK 用于请求成功 。GET 档案成功,PUT, PATCH 更新成功
201 Create诶 用于请求 POST 成功建立资料。
204 No Content 用于请求 DELETE 成功。
400 Bad Request 用于请求 API 参数不正确的情况,例如传入的 JSON 格式错误。
401 Unauthorized 用于表示请求的 API 缺少身份验证资讯。
403 Forbidden 用于表示该资源不允许特定用户访问。
404 Not Found 用于表示请求一个不存在的资源。
更多详细的可以参考 HTTP Status Codes

如果你的 API 比较复杂,还是要有文件记录你的 error code 。

依据不同的 API 操作,定义适合的 HTTP 状态码和必要的错误资讯

( 回传一个 JSON 并且包含 error 属性,error 这个属性记录错误讯息)。

结论
这次和大家简单介绍了 RESTful API 的概念,基本上,还有很多可以研究,像是避免
API 被攻击,可以考虑启用 API 调用速率限制( Rate limiting),又或是 HTTP Cache
的机制,最后,欢迎大家进入 RESTful 的世界 😆

posted on 2022-05-14 13:51  小子有出息  阅读(1343)  评论(0编辑  收藏  举报

导航