API设计总结

介绍

我在 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 是一种可以使用 HTTP 协议在网络上调用的 API。API是“Application Programming”接口的缩写,是调用软件组件和外部接口的规范,即知道功能但不知道内容行为的函数的集合(你不需要知道)从外面。指

简单来说就是一个web系统,可以通过访问URI来重写服务器端的信息,获取放置在服务器端的信息。

被解释。

通过使用 Web API,Web 服务(Twitter、Hot Pepper 等)提供的功能和数据可以以易于程序从外部读取的形式使用。

具体来说通过使用,您可以轻松获取餐厅数据。

网络如何运作

一个超级简化的总结如下。

用户(客户端)向 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

188人参与, 0条评论 登录后显示评论回复

你需要登录后才能评论 登录/ 注册