介绍
我在 2021 年作为一名应届毕业生加入了一家网络开发公司,担任前端工程师,并将在 2022 年进入我的第二年。
在实践中,我使用 React x TypeScript 开发前端,使用 Node.js (Nest) 和 Rails 开发后端 (API)。
重新学习了一下里面用到的API设计,所以总结一下。
本文的目标读者
- 工程师初级到中级
- 想要了解更多关于 API 的人
本文的目标
- 了解 API
- 了解正确的 API 设计,而不是您自己的
这篇文章没有做什么
- 描述如何使用特定代码编写 API 设计
关于这一点,我们计划在另一篇文章中总结 OpenAPI x Swagger。
关于 API
什么是 API
API是“Application Programming Interface”的缩写,字面意思是“使用应用程序编程进行连接“代表着。
什么是 Web API
什么是 Web API?Web API 好的部分在
Web API 是一种可以使用 HTTP 协议在网络上调用的 API。
API是“Application Programming”接口的缩写,是调用软件组件和外部接口的规范,即知道功能但不知道内容行为的函数的集合(你不需要知道)从外面。指简单来说就是一个web系统,可以通过访问URI来重写服务器端的信息,获取放置在服务器端的信息。
被解释。
通过使用 Web API,Web 服务(Twitter、Hot Pepper 等)提供的功能和数据可以以易于程序从外部读取的形式使用。
具体来说Hot Pepper 发布的 API通过使用,您可以轻松获取餐厅数据。
网络如何运作
一个超级简化的总结如下。
- 用户(客户端)向 Web 发送 HTTP 请求
- 请求的 Web 服务器返回数据
关于 HTTP 请求
具体来说,从 Web 浏览器向 Web 服务器发送的 HTTP 请求是
- 请求行
- 标题
- 身体
由三个要素组成。
请求行
作为 HTTP 请求的内容之一的请求行如下所示。
GET /index.html HTTP/1.1在请求行“你想要什么”写,配置如下。
- 方法
- 请求 URI
- HTTP 版本
具体方法包括GET(数据获取)、POST(数据注册)、PUT(数据更新)和DELETE(数据删除)。
请求头
请求标头包含有关请求的信息和属性(元数据)。
Host: localhost:8080 Connection: keep-alive User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.98 Safari/537.36 Accept: */* Referer: http://localhost:8080/ Accept-Encoding: gzip, deflate, sdch, br Accept-Language: ja,en-US;q=0.8,en;q=0.6 Cookie: user_id=12345678请求正文
实际随请求发送的数据进来了。
回复
当我发送 HTTP 请求时,响应具有以下结构
- 状态行
- 标题
- 身体
状态行
状态行具有以下结构。
- HTTP 版本
- 状态码
- 短语
HTTP/1.1 200 OK以下是最常见状态代码的摘要。
- 2xx:请求成功
- 4xx:错误请求
- 5xx:服务器端错误
有关状态码的更详细说明,请参阅下面的文章。
标题
响应标头包含元信息。
alt-svc: quic=":443"; ma=2592000; v="44,43,39,35" cache-control: private, max-age=0 content-encoding: br content-type: text/html; charset=UTF-8 date: Thu, 23 Aug 2018 15:37:28 GMT expires: -1 server: gws status: 200 x-frame-options: SAMEORIGIN x-xss-protection: 1; mode=block身体
返回来自服务器端的特定响应数据。
关于 REST
REST 描述如下。
REST 是适用于链接分布式系统中的多个软件的设计原则之一。它是由 Roy Fielding 在 2000 年提出的。狭义上是指应用在Web系统上的软件的设计风格,在大多数情况下一般都是在这个意义上使用的。
简单地说,REST 的意思是“设计规则”。
RESTful
RESTful 意味着遵循 REST 要求的原则。
RESTful API 是指根据 REST 原则设计的 API。
REST 原则
REST 有六个原则:
- 客户端-服务器约束
- 无状态
- 缓存(客户端)
- 统一接口
- 图层系统
- 按需编码
客户端-服务器约束
这个想法是客户端和服务器应该是独立的和独立的,并且应该结构化,以便它们可以在不相互影响的情况下进行改进。
换句话说,将客户端(屏幕 UI)和服务器(数据)之间的关注点分开。
无国籍
这意味着每个请求都独立完成而不保留先前的状态。
简而言之,
- 不要使用服务器上保存的上下文信息(不要使用服务器会话)
- 状态保存在客户端(全部包含在请求中)
缓存(客户端)
客户端可以缓存响应。
适当的缓存可以减少客户端和服务器之间的通信,改善用户体验,节省资源。
统一接口
对同一资源的所有 API 访问都以相同的格式统一(可通过唯一的 URI 访问)。
此外,只能使用 HTTP 协议方法(GET、POST、PUT、DELETE 等)进行数据操作。
通过统一 URI 操作(GET 和 POST),可以简化整体配置。
层系统
通过组合具有多个角色的服务器来实现 API 的架构称为层系统。
具体分为接收请求的层、返回响应的层和进行安全处理的层。
分层系统可以通过使每个角色独立来增加重用。
按需编码
您可以下载客户端代码并运行它。
通过加入按需代码,可以在服务器的主动下向已经发布的客户端添加功能,并且由于处理是在客户端实现的,因此可以减轻服务器的负载。
总结 REST 的原理。
- 客户端-服务器约束
- 无状态
- 缓存(客户端)
- 统一接口
- 图层系统
- 按需编码
Web API 设计
从这里,我们将学习Web API的设计,这是本次的主要主题。
URI设计
- 简短且易于键入
- 不要省略
- 不混合大小写(基本为小写)
- 单词被连字符
- 对单词使用复数形式
- 不要使用需要编码的字符
- 易于更新
- 规则统一
我一个一个看
简短易打字
省略无用信息(重复信息)以创建简洁的 URI。
[坏的]
https://exmaple.com/service/api/search[好的]
https://exmaple.com/search不要省略
[坏的]
https://exmaple.com/ja/u[好的]
https://exmaple.com/users大写和小写字母不混用(基数为小写)
一般来说,使用小写字母。混合大写和小写字母很容易导致混淆。
[坏的]
https://exmaple.com/Posts[好的]
https://exmaple.com/posts连字符
使用连字符连接单词。
[坏的]
https://exmaple.com/favorite_contents[好的]
https://exmaple.com/favorite-contents* 如果首先需要连接单词,则可能会审查 URI 设计。
https://exmaple.com/favorite/contents使用复数形式的单词
[坏的]
https://exmaple.com/post/1[好的]
https://exmaple.com/posts/1不要使用需要编码的字符
编码会降低可读性,并且无法从 URI 中猜测处理过程
[坏的]
https://exmaple.com/%TENFLOJFL$JSKF3352nb%scsd%易于更新
[坏的]
https://exmaple.com/alpha/contents/1 https://exmaple.com/beta/contents/1[好的]
https://exmaple.com/contents/1统一规则
统一规则,例如是否将参数作为路径参数或查询参数传递。
https://exmaple.com/beta/contents/1 # パスパラメタ https://exmaple.com/alpha/contents/?id=1 # クエリパラメタ总结 URI 设计
- 简短且易于键入
- 不要省略
- 不混合大小写(基本为小写)
- 单词被连字符
- 对单词使用复数形式
- 不要使用需要编码的字符
- 易于更新
- 统一规则
HTTP方法
前面介绍的URI表示资源,HTTP方法表示对资源的操作。
具体来说,在以下情况下,向资源
/api/v1/posts/1发送请求以获取数据(GET)。GET /api/v1/posts/1主要的HTTP方法如下。
方法名称 处理内容 得到 获取资源 邮政 新资源注册 放 更新现有资源 删除 删除资源 您可以通过更改相同 URI 的方法来更改操作。
手术 蜜蜂 获取文章列表 GET方法/http:///example.com/api/v1/posts 获取单篇文章 GET方法/http:///example.com/api/v1/posts/1 创建新文章 POST 方法/http:///example.com/api/v1/posts 文章更新 PUT 方法/http:///example.com/api/v1/posts/1 删除文章 删除方法/http:///example.com/api/v1/posts/1 查询参数和路径参数
类型 蜜蜂 查询参数 http:///example.com/api/v1/posts?id=1 路径参数 http:///example.com/api/v1/posts/1 何时使用查询参数和路径参数
- 表示唯一资源路径参数利用
- 如果可以省略查询参数
具体而言,使用查询参数是因为无法确定搜索请求的唯一路径。
http:///example.com/api/v1/users?name="suzuki"状态码
状态码给出了处理结果的概览。
即使发生特定错误,您也可以通过跟踪状态代码来识别错误。
有关状态代码,请参阅本文。
响应数据格式
主要响应数据的格式如下。
- XML
- JSON
XML
XML的特点如下。
- 文本格式在
- 标签中描述
- 标签是嵌套的
- 标签有属性
[XML 格式]
<login> <username>useremail@company.com</username> <password>mypassword</password> </login>JSON
JSON的特点如下。
- 文本格式
- 基于 JavaScript 的格式
- 与 XML 相比,可以减少数据量
- 对象可以嵌套
[JSON格式]
{ user: {"id" : "1", "name" : "tanaka"} }在指定数据格式时,最好在请求头中进行描述。
[请求头]
GET http://example.com/users Host: exmaple.com Acceot: application/json # JSON形式と指定した場合数据内部结构设计
- 不要使用信封
- 减少嵌套
- 统一属性命名约定
- 指定日期
不要使用信封
不要使用信封,它是返回 JSON 的 API 的常见部分。
下面响应中包含的“header”部分与请求头中传递的描述相同,因此不需要。 (涵盖的信息)
[有信封时 (BAD)]
{ "header": { "code": "0", "message": "success" }, "result": { "books": [ { "id": 1, "name": "初めてのJavaScript", "price": 3000 }, { "id": 2, "name": "はじめてのAPI入門", "price": 1500 } ] } }[省略信封时(GOOD)]
{ "books": [ { "id": 1, "name": "はじめてのJavaScript", "price": 3000 }, { "id": 2, "name": "はじめてのAPI入門", "price": 1500 } ] }减少嵌套
嵌套增加了响应能力,因此设计响应以减少不必要的嵌套。
[如果有不必要的嵌套 (BAD)]
{ "id": 2, "name": "はじめてのAPI入門", "info" : { "author": "tanaka", "price": 1500 } }[省略不必要的嵌套时(好)]
{ "id": 2, "name": "はじめてのAPI入門", "author": "tanaka", "price": 1500 }统一属性命名约定
一般使用蛇皮套或骆驼皮套。
姓名 例子 蛇案 蛇案例 骆驼香烟盒 骆驼香烟盒 帕斯卡案例 帕斯卡案例 日期指定
对日期使用 RFC3339 (W3C-DTF) 格式
2022-10-31T18:00:00+09:00错误
将错误详细信息添加到响应正文。
{ "code": "12345", "message": "認証エラーです" }此外,发生错误时,请勿以 HTML 格式响应。
根据格式,可能无法在客户端处理它。
其他设计
认证
JSON 网络令牌
JSON Web Token (JWT) 被称为“jot”,通过签名对 JSON 格式的数据进行篡改检查。
通过使用 JWT,可以将认证结果存储在客户端,而无需存储在服务器端,实现无状态通信。
JWT的结构如下。
- 标题
- 有效载荷
- 签名
[智威汤逊示例]
eyJhbGcGKOWJIUzI1NiI&3Hf5cCI6IkpXVCJ9. eyJzdWIiOiIxMjMPqfwibmFtZSIfksjDTW3nwoAOCWQ0IjoxNTE2MjM5MDIyfQ. t42p4AHef69Tyyi880842bDTTOADINW93ncs7Zffs.,实际上具有以下结构
[ヘッダ]. [ペイロード]. [署名]标头具体定义了签名中使用的算法。
【标题】
{ "alg": "HS256", "typ": "JWT" }有效负载包含您要存储的实际数据。
- sub 是同一颁发者中的标识符(用户 ID 等)
- iat 表示发出 jwt 的日期和时间
【有效载荷】
{ "sub": "1234567890", "iat": 1516239022 }签名验证数据未被篡改。
授权标头
有一个 Authorization 标头作为用于身份验证的标头。
使用前面介绍的 JWT 时,将令牌存储在 Authorization 标头中并发送请求。
它以以下格式描述。
Authorization: [type] [credentials]
[type]的类型如下。
姓名 解释 基本的 使用基本身份验证以纯文本形式发送 ID 和密码 承载 JWT 在 OAuth2.0 中使用它 消化 散列和发送带有摘要认证的 ID 和密码 身份验证 OAuth 1.0 此外,
[credentials]将包含特定的身份验证信息。使用著名的身份验证方法 Auth0,您可以使用 JWT 令牌在请求标头中包含以下信息,从而与服务器端交换数据。
Authorization: Bearer eyxxxxxxxxx安全
我们将解释以下漏洞对策。
- XSS
- CSRF
- HTTP
- 智威汤逊
跨站脚本
XSS 允许恶意用户在合法站点上嵌入恶意脚本,并非法提取有关合法用户的信息。
作为对策,将以下内容添加到响应标头中
X-XSS-Protection: 1 启用 XSS 过滤X-Frame-Options: 用 DENY 拒绝调用帧标签X-Content-Type-Options: 使用 nosniff 解决 IE 漏洞CSRF
处理来自应拒绝的访问源的请求。
以下是对策
- 未经许可拒绝请求
- X-API-密钥
- 身份验证
- 恶意攻击者发出难以猜测的令牌并执行验证
- X-CSRF-TOKEN
HTTP
由于 HTTP 通信路径没有加密,因此很容易被窃听。
作为对策,请使用 HTTPS。
智威汤逊
前面介绍的JWT可以在客户端进行编辑,所以如果服务端验证不充分,就有可能接受被篡改的信息。
作为对策,不要为标头算法 (alg) 指定 none。
在最后
怎么样。这里是 API 设计的总结。
我正在写其他各种文章,所以如果您能阅读它,我会很高兴。
参考
原创声明:本文系作者授权爱码网发表,未经许可,不得转载;
原文地址:https://www.likecs.com/show-308632569.html