如何构建 REST API?
本文将介绍 API,特别是 RESTful API。我们将探讨其优点、局限性和替代方案。此外,我们还将演示如何使用最佳 BaaS 提供商之一Back4app构建 REST API。
Contents
什么是应用程序接口?
应用程序接口(API)是一组定义两个设备或系统如何相互通信的规则。API 由开发人员创建,旨在供其他开发人员或系统使用,而不是直接供最终用户使用。终端用户通常通过所谓的前端或客户端间接使用它们。
你可以把应用程序接口看作是客户端与资源或网络服务之间的中介。客户端发送请求,然后对请求进行处理,最后返回资源或响应。
如今,应用程序接口几乎无处不在。大多数企业都有多个内部和公开访问的 API。就在今天,你可能已经与上百个 API 进行了交互。例如,当您查看时间、天气、浏览 Facebook 或观看 YouTube 视频时。
应用程序接口(API)和 SDK 有什么区别?
如上所述,API 是一组定义两个设备或系统如何进行通信的规则。另一方面,软件开发工具包(SDK)是工具、库和文档的集合,可帮助开发人员为特定平台(如 Windows、Web、Android、iOS)构建软件。
SDK 通常在幕后使用各种 API。我们将在文章的第二部分介绍一个实际例子。
什么是 REST?
被称为 “表征状态转移(REST)”的软件架构方法是互联网框架的特征。它不构成协议或标准,允许开发人员采用不同的实现方法。罗伊-菲尔丁(Roy Fielding)于 2000 年提出了 REST,十多年来,它一直是创建网络应用程序接口的主要标准。
REST 基于 HTTP 协议,利用不同的 HTTP 方法(如GET
、POST
、PUT
和DELETE
)来操作资源。这些操作通常被称为 CRUD(创建检索更新删除)。REST 支持多种数据格式,包括 JSON、HTML、XLT、Python、JavaScript 等。最常用的数据格式是 JSON。
一个应用程序接口要想被视为 RESTful,必须符合以下六项约束条件:
- 客户端和服务器架构— 客户端和服务器组件应分开。
- 无状态— 服务器应用程序不得在请求之间存储任何客户端数据。
- 可缓存性— 在可能的情况下,资源应可在客户端或服务器端缓存。
- 分层系统— 应用程序接口应允许有中间人,但这不应影响客户端。
- 统一接口— 服务器和客户端之间的接口应统一。
- 按需代码(可选)–允许服务器向客户端发送可执行代码。
REST 和 RESTful 的区别在于,REST 指的是一系列约束条件,而 RESTful 指的是符合这些约束条件的应用程序接口。
RESTful API 如何工作?
RESTful API 的工作方式与浏览器类似。主要区别在于,浏览器使用 HTTP 向服务器请求网页和其他资源,而 RESTful API 使用 HTTP 请求和操作数据资源。
典型的 RESTful API 调用遵循以下步骤:
- 客户端向服务器发送请求。
- 服务器对客户端进行身份验证,并检查客户端是否有足够的权限处理请求。
- 服务器处理请求,例如执行计算,并从数据库中获取数据。
- 服务器向客户端返回响应。
- 客户端处理响应。
根据 API 的实现,步骤可能会有所不同。API 参考资料(或 API 文档)中定义了如何使用 API 的说明。
申请结构
申请包含以下内容
财产 | 说明 |
---|---|
通用资源识别号 | 定义服务器应操作的资源。URL 还可以包含查询参数,用于对结果进行过滤或排序。 |
HTTP 方法 | 告诉服务器如何处理该资源。例如,GET 返回资源,POST 添加新资源,PUT 更新现有资源,DELETE 删除资源。 |
页眉(可选) | 包含请求的元数据,如身份验证信息、cookie、用户代理和内容类型。 |
机身(可选) | 包含执行所请求操作的附加信息。 |
请求示例如下
响应结构
答复内容如下
财产 | 说明 |
---|---|
状态代码 | 状态代码定义了请求是否成功(2xx )(4xx 、5xx )。 |
页眉 | 包含有关响应的元数据,如服务器时间、内容长度和内容类型。此外,服务器还可以使用Set-Cookie 标头在客户端设置 cookie。 |
身体 | 包含资源表示。表示格式基于请求的Content-Type 标头(如application/json )。 |
回复示例如下
RESTful API 有哪些优势?
可扩展性
RESTful API 具有高度可扩展性,可以纵向和横向扩展。添加新的端点或资源对应用程序接口的性能影响极小,因此很容易根据需要进行扩展。
多种数据格式
RESTful 应用程序接口可根据客户端的请求标头以不同格式返回数据。这使得它们非常灵活,易于集成到现有系统中。数据可以 JSON、XLT、Python、HTML、JavaScript 等格式返回。
效率
与 SOAP(简单对象访问协议)相比,RESTful API 重量轻、开销小。这使得它们能快速高效地处理请求。典型的 RESTful API 每秒可处理 10.000 到 15.000 个请求。
平台独立性
RESTful API 的另一大优点是服务器和客户端完全独立。这使得开发人员可以用 Java、JavaScript、Python 等多种编程语言实现 RESTful API 和客户端!
简单易懂
由于 REST 基于 HTTP,因此非常容易理解。大多数开发人员几乎肯定至少使用或实施过一次 RESTful API。
RESTful API 有哪些局限性?
数据抓取不足和抓取过度
RESTful API 的最大问题之一是数据抓取不足和抓取过度。当返回的数据多于需要时,就会出现过度抓取的情况,而当返回的数据不足时(主要是在处理关系时),就会出现抓取不足的情况。
无需订阅实时数据
RESTful API 不允许订阅数据更改。这意味着客户端需要轮询服务器才能检测到这些变化。轮询的效率极低,会导致不必要的网络流量、延迟增加、带宽使用率提高和可扩展性降低。
无版本系统
RESTful API 没有内置的版本系统。此外,也没有办法废弃字段,这使得随着时间的推移 API 难以发展。每次发布重大 API 更新时,您都不得不修改所有客户端。
为了解决上述问题,出现了几种 REST 替代方案。其中最流行的包括简单对象访问协议(SOAP)、GraphQL 和gRPC。
什么是 RESTful 身份验证方法?
RESTful API 可以使用不同的身份验证方法来确保其端点的安全。最常用的身份验证方法有
- HTTP 验证
- API 密钥
- OAuth 2.0
- OpenID Connect
- JWT 验证
这些方法大多要求客户端在请求头中发送凭据或 API 密钥。在启动项目时,应考虑不同的身份验证方法。
如何构建 RESTful API?
文章的这一部分将探讨如何使用 Back4app 构建 RESTful API 并与 Next.js 前端建立连接。
先决条件
- 使用 JavaScript ES6 的经验
- 具有使用 React 和 Next.js 的经验
- 对 REST 有基本了解
什么是 Back4app?
Back4app 是一款出色的 BaaS(后端即服务)解决方案。它使用开源软件,提供多种功能,帮助开发人员更快地开发移动和网络应用程序。这让企业可以专注于业务逻辑,而无需担心云基础设施。
该平台拥有用户友好型仪表板和命令行界面,提供与 Node.js、Flutter、React Native、Android、Angular 和 iOS 等广泛使用的工具兼容的软件开发工具包 (SDK)。
Back4app 的定价模式简单,适合任何应用程序。他们还有一个免费计划,不需要信用卡,是开发、测试和原型设计的好选择。
要了解有关 Back4app 的更多信息,请阅读什么是 Back4app?
项目介绍
在本文中,我们将构建一个简单的博客网络应用程序。该网络应用程序将允许编辑添加文章,并允许用户阅读文章。应用程序将分为两部分:后台(基于 REST)和前台。后端将使用 Back4app,前端将使用React和 Next.js。
后台
创建 Back4app 应用程序
导航至 Back4app 面板,点击 “创建新应用程序 “创建新应用程序。
选择 “Backend as a Service (BaaS)”,为其自定义名称,并选择 “NoSQL Database “作为数据库。最后,单击 “创建 “开始应用程序创建过程。
Back4app 会花一些时间准备应用程序所需的一切,如数据库、扩展和安全。应用程序准备就绪后,您将被重定向到 “数据库 “视图。
定义数据库类
接下来,让我们定义数据库类。
我们将开设以下两门课
ArticleCategory
表示文章类别(如区块链、人工智能、编程)文章
代表一篇文章。一篇文章可以有多个类别(M:N)。
要创建一个类,请访问 Back4app 面板,选择侧边栏上的 “数据库”。然后点击 “创建类”,将其命名为ArticleCategoy
,并启用 “公共读写”。
在转入生产阶段时,应禁用 “公共读写”,并使用 ACL 和 CLP 加强安全性。更多信息,请查看Parse 服务器安全。
然后,添加以下字段:
+-----------------------------+-----------------+--------------------+-------------+
| Data type | Name | Default value | Required |
+-----------------------------+-----------------+--------------------+-------------+
| String | name | <leave blank> | yes |
+-----------------------------+-----------------+--------------------+-------------+
| String | slug | <leave blank> | yes |
+-----------------------------+-----------------+--------------------+-------------+
| String | description | <leave blank> | no |
+-----------------------------+-----------------+--------------------+-------------+
对第二个名为 “文章 "
的类执行相同步骤。添加以下字段:
+-----------------------------+-----------------+--------------------+-------------+
| Data type | Name | Default value | Required |
+-----------------------------+-----------------+--------------------+-------------+
| String | title | <leave blank> | yes |
+-----------------------------+-----------------+--------------------+-------------+
| String | slug | <leave blank> | yes |
+-----------------------------+-----------------+--------------------+-------------+
| String | shortContent | <leave blank> | yes |
+-----------------------------+-----------------+--------------------+-------------+
| String | content | <leave blank> | yes |
+-----------------------------+-----------------+--------------------+-------------+
| Relation -> ArticleCategory | categories | <leave blank> | no |
+-----------------------------+-----------------+--------------------+-------------+
很好,就是这样。
填充数据库
在今后测试 API 的步骤中,我们需要一些数据来使用。在数据库中填充一些文章类别和文章示例。
要添加新的文章类别
,请在侧边栏中选择该类别
,然后点击 “添加一行”。
您可以使用这些文章类别,也可以自设类别:
+------------+------------+---------------------------------------------------------+
| name | slug | description |
+------------+------------+---------------------------------------------------------+
| Blockchain | blockchain | Blockchain, crypto & more! |
+------------+------------+---------------------------------------------------------+
| AI | ai | Artificial intelligence, LLMs, stable diffusion. |
+------------+------------+---------------------------------------------------------+
您还可以使用 ChatGPT 生成样本数据。要了解有关 ChatGPT 的更多信息,请查看如何使用 ChatGPT 构建应用程序?
对 “文章
“类做同样的处理:
+------------------+---------------+--------------+---------+-----------------------+
| title | slug | shortContent | content | categories |
+------------------+---------------+--------------+---------+-----------------------+
| Beyond Crypto | beyond-crypto | ... | ... | <blockchain.objectId> |
+------------------+---------------+--------------+---------+-----------------------+
| The Rise of AI | rise-of-ai | ... | ... | <ai.objectId> |
+------------------+---------------+--------------+---------+-----------------------+
| What is ChatGPT? | chatgpt | ... | ... | <ai.objectId> |
+------------------+---------------+--------------+---------+-----------------------+
确保更换 和
替换为实际的
ArticleCategory
objectId
。在我的例子中,它们是SxS0yiWDij
和Hf8yBDTO79
(上图供参考)。
REST API
Back4app 最棒的地方在于,当您定义数据库类时,Back4app 会自动为您设置 REST API。生成的 REST API 允许您对数据库中的所有类执行基本的 CRUD 操作。
REST API 控制台
要测试 API,请导航至 Back4app 面板,选择侧边栏上的 “API > 控制台 > REST”。然后选择GET
作为请求类型,classes/Article
作为端点。最后,单击屏幕右下方的 “发送查询 “以发送请求。
该请求将返回数据库中的所有文章。您应该会得到类似的响应:
{
"results":[
{
"objectId": "yEaR8K44il",
"title": "Beyond Crypto",
"slug": "beyond-crypto",
"shortContent": "...",
"content": "...",
"createdAt": "2023-04-17T14:26:19.016Z",
"updatedAt": "2023-04-17T14:26:30.922Z",
"categories": {
"__type": "Relation",
"className": "ArticleCategory"
}
},
{
"objectId": "l46nMkHElH",
"title": "What is ChatGPT?",
"slug": "chatgpt",
"shortContent": "...",
"content": "...",
"createdAt": "2023-04-17T14:27:34.931Z",
"updatedAt": "2023-04-17T14:27:42.636Z",
"categories": {
"__type": "Relation",
"className": "ArticleCategory"
}
}
// ...
]
}
REST 控制台还允许你执行POST
、PUT
和DELETE
操作。此外,您还可以使用解析查询参数过滤数据、处理关系等。
例如,如果您想获取属于 “区块链 “类别的文章,可以使用以下where
语句:
where={"categories": {
"__type": "Pointer", "className": "ArticleCategory", "objectId": "<objectId>"
}}
确保将 替换为区块链的
objectId
。
查看Parse REST API 指南,了解有关查询参数的更多信息。
cURL
REST 控制台很不错,但当你在实际应用中工作时,你会需要一种更面向程序员的方法来处理 API 请求。你可以使用的工具之一是cURL,它是一个用于 HTTP、FTP 和 SMTP 等各种协议的命令行工具。
列出文章类别的 cURL 命令示例如下:
$ curl -X GET \
-H "X-Parse-Application-Id: YOUR_APPLICATION_ID" \
-H "X-Parse-REST-API-Key: YOUR_REST_API_KEY" \
https://parseapi.back4app.com/classes/ArticleCategory | jq
您可以从 “Back4app 控制面板 > 应用程序设置 > 安全和密钥 “中获取密钥。
如您所见,使用 cURL 时,您必须指定 HTTP 方法类型,并提供应用程序 ID 和 REST API 密钥。此外,您还可以将响应导入jq,使其自动格式化并用颜色突出显示。
应用程序接口参考
Back4app 的另一大优点是,它会自动为所有数据库类生成 API 参考。每次更改都会反映在文档中。
要访问 API 参考,请选择侧边栏上的 “数据库”,然后使用屏幕右上方的三个点查看所有选项。最后,选择 “API 参考”。
API 参考资料包含所有数据库类的说明、CRUD 操作说明、请求示例、响应示例和代码片段。
这就是后台。在下一节中,我们将了解如何实现可与后台通信的前台。
前端
如上所述,我们将使用 React 和 Next.js 13 来构建前端。一般来说,有三种方法可以从 JavaScript 前端连接到基于 Parse 的后端:
- 使用 REST API(HTTP 请求和响应)
- 通过使用 GraphQL 应用程序接口(本文将对此进行介绍)
- 使用JavaScript SDK
你应该选择最后一个或倒数第二个选项。在可以使用 Parse SDK(如 JavaScript、Flutter、Android、iOS、Xamarin)的客户端应用程序中,不建议直接使用 REST API。这是因为 Parse SDK 可以让你编写更简洁的代码,而且不容易出错。在幕后,Parse SDK使用REST API。
创建下一个应用程序
使用create-next-app
工具启动 Next.js 项目。打开终端,运行以下命令
$ yarn create next-app
√ What is your project named? ... back4app-graphql
√ Would you like to use TypeScript with this project? ... No
√ Would you like to use ESLint with this project? ... Yes
√ Would you like to use the `src/` directory with this project? ... No
√ Would you like to use the experimental `app/` directory with this project? ... No
√ What import alias would you like configured? ... @/*
Successfully created a Next.js app.
接下来,运行开发服务器:
$ yarn dev
导航至http://localhost:3000,你应该会看到 Next.js 登陆页面。
脉动UI
为了让 UI/UX 构建过程更简单,我们将使用ChakraUI。Chakra UI 是一个简单、模块化和用户友好的组件库,它提供了开发 React 应用程序所需的所有元素。
如果遇到任何问题,请参阅ChakraUI:开始使用 Next.js。
首先运行以下命令安装 Chakra 及其依赖程序:
yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
接下来,导航到_pages/app.tsx,然后像这样用ChakraProvider
封装应用程序:
// pages/_app.tsx
import "../styles/globals.css";
import {ChakraProvider, extendTheme} from "@chakra-ui/react";
export const theme = extendTheme({});
function MyApp({ Component, pageProps }) {
return (
<ChakraProvider theme={theme}>
<Component {...pageProps} />
</ChakraProvider>
);
}
export default MyApp;
不要忘记导入ChakraProvider
:
import {ChakraProvider} from "@chakra-ui/provider";
在内容之前加载颜色模式脚本,以避免随机颜色闪烁。为此,您可以像这样使用_document.js :
// pages/_document.js
import {ColorModeScript} from "@chakra-ui/react";
import { Html, Head, Main, NextScript } from "next/document";
import {theme} from "@/pages/_app";
export default function Document() {
return (
<Html lang='en'>
<Head />
<body>
<ColorModeScript initialColorMode={theme.config.initialColorMode} />
<Main />
<NextScript />
</body>
</Html>
);
}
很好,您已成功安装 ChakraUI。
用户界面
下面我们来实现用户界面。我们将创建以下两个页面:
/
显示文章列表/
/ 显示特定文章
从索引开始。用以下内容替换pages/index.js内容:
// pages/index.js
import {Card, CardBody, Container, Heading,
Link, Spinner, Stack, Text} from "@chakra-ui/react";
import NextLink from "next/link";
import {useEffect, useState} from "react";
export default function Home() {
const [isLoading, setIsLoading] = useState(true);
const [articles, setArticles] = useState([]);
return (
<>
<main>
<Container maxW="container.lg">
<Heading as="h1" my="4">
back4app-rest
</Heading>
{isLoading ? (
<Spinner size="lg"/>
) : (
<Stack spacing="4" direction="column">
{articles.map((article, index) => (
<Card key={index} w="100%">
<CardBody>
<Stack spacing="3">
<Heading size="md">
<Link as={NextLink} href={article.get("slug")}>
{article.get("title")}
</Link>
</Heading>
<Text>
{article.get("shortContent")}
</Text>
</Stack>
</CardBody>
</Card>
))}
</Stack>
)}
</Container>
</main>
</>
);
}
- 我们准备了
文章
和isLoading
状态,稍后在获取数据时会用到。 - 我们使用基本的 ChakraUI 组件来设计用户界面。
- 为了显示所有文章,我们循环浏览
文章
状态。
接下来,导航至pages/[slug].js,并将其更改为以下内容:
// pages/[slug].js
import {useRouter} from "next/router";
import {Card, CardBody, Container, Heading,
Link, Spinner, Stack, Text} from "@chakra-ui/react";
import NextLink from "next/link";
import {useEffect, useState} from "react";
export default function Article() {
const router = useRouter();
const {slug} = router.query;
const [isLoading, setIsLoading] = useState(true);
const [article, setArticle] = useState(null);
return (
<>
<main>
<Container maxW="container.lg">
<Heading as="h1" my="4">
back4app-rest
</Heading>
{isLoading ? (
<Spinner size="lg"/>
) : (
<>
{article == null ? (
<Text>This article does not exist.</Text>
) : (
<Card w="100%">
<CardBody>
<Stack spacing="3">
<Heading size="md">{article.get("title")}</Heading>
<Text>
{article.get("content")}
</Text>
<Text fontSize="sm">
Posted on {new Date(article.get("createdAt")).toDateString()}
</Text>
</Stack>
</CardBody>
</Card>
)}
</>
)}
<Text size="sm" mt="2" align="right">
<Link as={NextLink} href="/">← Go back</Link>
</Text>
</Container>
</main>
</>
);
}
- 我们准备了
文章
状态来保存文章。 - 我们使用 Next Router 从 URL 获取
slug
参数。
后台集成
在最后一部分,我们将连接前台和后台。
要使用 Parse SDK,我们首先要安装它。运行以下命令
$ yarn add parse @react-native-async-storage/async-storage
接下来,导航至Pages/_app.js,然后像这样初始化 Parse:
// pages/_app.js
const PARSE_HOST_URL = "https://parseapi.back4app.com/";
Parse.initialize("YOUR_APPLICATION_ID", "YOUR_JAVASCRIPT_KEY"); // replace me
Parse.serverURL = PARSE_HOST_URL;
export default function App({ Component, pageProps }) {
return (
// ...
);
}
别忘了进口:
import Parse from "parse/dist/parse.min.js";
我们可以使用Parse.Query
来获取索引页面上的文章。获取数据后,我们可以将其存储在文章
中,并将isLoading
设置为false
:
// pages/index.js
export default function Home() {
// ...
const getArticles = async () => {
const query = new Parse.Query("Article");
setArticles(await query.find());
setIsLoading(false);
};
useEffect(() => {
getArticles();
}, []);
return (
// ...
);
}
然后,我们可以在pages/[slug].js 中对文章进行类似处理:
// pages/[slug].js
export default function Article() {
// ...
const getArticle = async () => {
const query = new Parse.Query("Article");
query.equalTo("slug", slug);
const results = await query.find();
setIsLoading(false);
if (results.length === 0) return;
setArticle(results[0]);
};
useEffect(() => {
getArticle();
}, []);
return (
// ...
);
}
同样,别忘了在两个文件中都导入 Parse。
import Parse from "parse/dist/parse.min.js";
启动 Next 开发服务器(如果尚未运行),并在您最喜欢的网络浏览器中访问http://localhost:3000。您应该可以看到文章列表,而且文章应该可以阅读。
结论
在本文中,您已经了解了 API、RESTful API 及其优缺点。现在,您应该能够构建简单的 RESTful API 并从前端应用程序连接到它们。
您可以在GitHub 上获取最终源代码。
如果您喜欢这篇文章,请查看如何制作 GraphQL API 一文。