API 设计:使用 Node.js 和 Express.js 的综合教程

API(应用程序编程接口)设计涉及创建一个高效而强大的接口,允许不同的软件应用程序相互交互。

说明

        本教程将指导您使用 Node.js 和 Express.js 作为核心技术来规划、设计和构建 API。但是,这些原则可以应用于任何语言或框架。我们将创建一个简单的在线市场 API 作为工作示例。

        让我们开始吧!

第 I 部分:规划 API

  1. 确定目的:设计 API 的第一步是确定它的用途。我们的 API 适用于在线市场,用户可以在其中查看待售商品并进行购买。
  2. 定义资源:接下来,确定 API 将处理的不同类型的数据。对于我们的市场,我们需要“物品”和“购买”的资源。
  3. 设计终结点:每个资源都应具有一组关联的终结点,这些终结点允许客户端与数据进行交互。使用 REST 原则,我们将为“项目”和“购买”创建终结点。

以下是 API 端点的粗略草图:

  • GET /items:获取所有项目
  • GET /items/:id:获取特定项目
  • POST /items:添加新项目(仅限管理员)
  • DELETE /items/:id:删除项目(仅限管理员)
  • POST /purchases:进行新的购买

第 II 部分:构建 API

在本教程中,需要在计算机上安装 Node.js 和 npm。为您的项目创建一个新目录,在终端中导航到该目录,然后初始化一个新的 Node.js 项目:

mkdir marketplace-api && cd marketplace-api
npm init -y

接下来,安装 Express.js,一个流行的 Node.js Web 框架:

npm install express

2.1 设置服务器

让我们从设置一个基本的 Express 服务器开始。创建一个名为 :app.js

const express = require('express');
const app = express();

app.listen(3000, () => console.log('Server listening on port 3000'));

您可以使用 启动服务器。服务器将在端口 3000 上启动。node app.js

2.2 创建终结点

        让我们创建之前计划的终结点。首先,我们需要定义我们的数据。为简单起见,我们将使用内存中数组来存储数据:

let items = [];
let purchases = [];

        我们还需要安装和使用 body-parser 中间件,以便 Express 能够理解 JSON body:

npm install body-parser

        然后,在:app.js

const bodyParser = require('body-parser');
app.use(bodyParser.json());

        现在,让我们创建终结点。以下是实现它们的方法:

        查看所有项目:

app.get('/items', (req, res) => {
    res.json(items);
});

        查看特定项目:

app.get('/items/:id', (req, res) => {
    const item = items.find(i => i.id === parseInt(req.params.id));
    if (!item) return res.status(404).send('Item not found');
    res.json(item);
});

        添加项目(仅限管理员):

app.post('/items', (req, res) => {
    // This should be protected
    const newItem = {
        id: items.length + 1,
        name: req.body.name,
        price: req.body.price
    };
    items.push(newItem);
    res.status(201).json(newItem);
});

        删除项目(仅限管理员):

app.delete('/items/:id', (req, res) => {
    // This should be protected
    const itemIndex = items.findIndex(i => i.id === parseInt(req.params.id));
    if (itemIndex === -1) return res.status(404).send('Item not found');
    const deletedItem = items.splice(itemIndex, 1);
    res.json(deletedItem);
});

        进行购买:

app.post('/purchases', (req, res) => {
    // This should also check if the item exists and if the user has enough funds
    const newPurchase = {
        id: purchases.length + 1,
        userId: req.body.userId,
        itemId: req.body.itemId,
    };
    purchases.push(newPurchase);
    res.status(201).json(newPurchase);
});

第III 部分: 测试您的 API

        您可以使用 Postman 或 curl 等工具测试您的 API。确保每个终结点都按预期运行并正确处理错误。始终使用不同类型的输入和场景进行测试,以确保 API 可靠。

第 IV 部分:记录 API

        好的 API 文档可以包括概述、身份验证步骤、端点描述、错误代码和示例。您可以手动创建 API 文档,也可以使用工具自动生成 API 文档。

        对于 Node.js,您可以使用 Swagger UI Express 等工具自动生成交互式文档。以下是有关如何设置它的快速示例:

  1. 安装必要的模块:
npm install swagger-ui-express yamljs

2. 创建一个新的 Swagger 规范文件:swagger.yaml

swagger: "2.0"
info:
  version: "1.0.0"
  title: "Marketplace API"
paths:
  /items:
    get:
      summary: "Get all items"
      responses:
        200:
          description: "A list of items"
          schema:
            $ref: '#/definitions/Item'
definitions:
  Item:
    type: "object"
    properties:
      id:
        type: "integer"
      name:
        type: "string"
      price:
        type: "number"

3. 在以下环境中导入并使用 Swagger UI:app.js

const swaggerUi = require('swagger-ui-express');
const YAML = require('yamljs');
const swaggerDocument = YAML.load('./swagger.yaml');

app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerDocument));

现在,您可以在 中查看 API 文档。localhost:3000/api-docs

第 V 部分:保护 API

您可以采取以下一些步骤来保护 API:

第 1 步:使用 HTTPS

Express.js 本身不支持 HTTPS,但在部署应用程序时,请确保使用支持 HTTPS 的提供程序,例如 AWS、Azure 或 Heroku。

第 2 步:身份验证

Express.js 没有内置的身份验证支持,但您可以使用 Passport.js 等中间件来处理此问题。

下面是如何设置基于令牌的身份验证的简化示例:

  1. 安装 Passport.js 和 JWT 策略:
npm install passport passport-jwt jsonwebtoken

2. 在您的 :app.js

const jwt = require('jsonwebtoken');
const passport = require('passport');
const JwtStrategy = require('passport-jwt').Strategy;

// Users should be stored in a database
let users = [{ id: '1', name: 'test', password: 'test', token: '' }];

// JWT strategy
passport.use(new JwtStrategy({ secretOrKey: 'secret' }, (jwtPayload, done) => {
    const user = users.find(user => user.id === jwtPayload.id);
    if (user) {
        return done(null, user);
    } else {
        return done(null, false);
    }
}));

// Login route
app.post('/login', (req, res) => {
    const user = users.find(user => user.name === req.body.username && user.password === req.body.password);
    if (user) {
        const token = jwt.sign({ id: user.id }, 'secret');
        user.token = token;
        res.json({ token });
    } else {
        res.sendStatus(401);
    }
});

// Protected route
app.post('/items', passport.authenticate('jwt', { session: false }), (req, res) => {
    // Process request...
});

此设置要求客户端在标头中发送令牌。BearerAuthorization

第 3 步:授权

对于授权,请在处理请求之前检查用户的角色。例如:

app.post('/items', passport.authenticate('jwt', { session: false }), (req, res) => {
    if (req.user.role !== 'admin') return res.sendStatus(403);
    // Process request...
});

第 4 步:速率限制

Express.js 本身不支持速率限制,但有一些中间件包可以使用:express-rate-limit

npm install express-rate-limit

然后,在您的 :app.js

const rateLimit = require('express-rate-limit');

const apiLimiter = rateLimit({
    windowMs: 15 * 60 * 1000, // 15 minutes
    max: 100
});

app.use('/api/', apiLimiter);

第 5 步:输入验证

始终验证 API 的输入。例如:

app.post('/items', (req, res) => {
    if (!req.body.name || !req.body.price) return res.status(400).send('Invalid input');
    // Process request...
});

第 6 步:错误处理

错误处理对于防止信息泄露非常重要。Express.js 会自动处理未捕获的异常并发送响应。自定义错误处理,如下所示:500 Internal Server Error

app.use((err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send('Something broke!');
});

        请记住,安全是一个持续的过程。始终了解最新的安全最佳实践,并定期审核 API 是否存在漏洞。瓦利德·穆萨

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/186749.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

APP软件外包开发需要注意的问题

在进行APP软件开发时,有一些关键问题需要特别注意,以确保项目的成功和用户满意度。以下是一些需要注意的问题,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 清晰的需求定义&a…

详解STUN与TR111

STUN协议定义了三类测试过程来检测NAT类型: Test1:STUN Client通过端口{IP-C1:Port-C1}向STUN Server{IP-S1:Port-S1}发送一个Binding Request(没有设置任何属性)。STUN Server收到该请求后,通过端口{IP-S1:Port-S1}把…

统计二叉树中的伪回文路径 : 用位运用来加速??

题目描述 这是 LeetCode 上的 「1457. 二叉树中的伪回文路径」 ,难度为 「中等」。 Tag : 「DFS」、「位运算」 给你一棵二叉树,每个节点的值为 1 到 9 。 我们称二叉树中的一条路径是 「伪回文」的,当它满足:路径经过的所有节点值…

一个正整数转为2进制和8进制,1的个数相同的第23个数是什么?

package cn.com;import java.lang.*;//默认加载public class C2 {//10进制转8进制static int HtoO(int n){int cnt 0;while(n!0){cntn%8;n/8;}return cnt;}//10进制转2进制static int HtoB(int n){int cnt 0;while(n!0){cntn%2;n/2;}return cnt;}public static void main(Str…

Windows服务设置多个服务依赖项避免服务启动失败找不到数据库

添加多个服务依赖项建议通过命令行的方式添加: winr键打开命令行 cmd 命令行添加命令如下: sc config "thinvent-auth" depend "MySQL57"/"RabbitMQ"/"Redis" sc config "服务A" depend "服务…

C#,《小白学程序》第十四课:随机数(Random)第一,几种随机数的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十四课&#xff1a;随机数&#xff08;Random&#xff09;第一&#xff0c;几种随机数的计算方法与代码 /// 本课初步接触一下随机数。 /// </summary> /// <param name"sender"></param> ///…

LiveVIS视图库1400-如何切换数据库?默认使用的数据库是什么?如何切换到Mysql/MariaDB?

LiveVIS视图库1400-如何切换数据库&#xff1f;默认使用的数据库是什么&#xff1f;如何切换到Mysql/MariaDB? 1、切换成Mysql/Mariadb数据库1.1 连接数据库1.2 创建数据库实例1.3 配置.ini文件1.4 重启完成切换 1、切换成Mysql/Mariadb数据库 LiveVIS 默认使用 sqlite3 文件…

重新开启GPT Plus充值通道——基于前端开发者工具

chatGPT PLUS充值通道的关闭 由于chatGPT用户激增&#xff0c;近日&#xff0c;OpenAI的CEO Sam Altman宣布需要暂停新用户对ChatGPT Plus的订阅。在X上&#xff0c;他表达了对于确保用户体验的承诺&#xff0c;同时也提到了用户可以通过应用程序内的通知功能来了解服务恢复的…

笔记本电脑可以投屏到电视吗?Win、Mac、Linux分别怎么投屏?

如果你的电视是安卓电视&#xff0c;那么答案是&#xff1a;完全可以&#xff01; 不管你的笔记本电脑是Windows系统、macOS系统还是Linux系统&#xff0c;你都可以借助AirDroid Cast的电脑客户端或网页版&#xff0c;将电脑屏幕投屏到安卓智能电视上。 首先&#xff0c;你需要…

Unity技美35——再URP管线环境下,配置post后期效果插件(post processing)

前两年在我的unity文章第10篇写过&#xff0c;后效滤镜的使用&#xff0c;那时候大部分项目用的还是unity的基础管线&#xff0c;stander管线。 但是现在随着unity的发展&#xff0c;大部分项目都用了URO管线&#xff0c;甚至很多PC端用的都是高效果的HDRP管线&#xff0c;这就…

网络数据结构skb_buff原理

skb_buff基本原理 内核中sk_buff结构体在各层协议之间传输不是用拷贝sk_buff结构体&#xff0c;而是通过增加协议头和移动指针来操作的。如果是从L4传输到L2&#xff0c;则是通过往sk_buff结构体中增加该层协议头来操作&#xff1b;如果是从L4到L2&#xff0c;则是通过移动sk_…

井盖位移传感器怎么监测井盖安全

井盖在城市基础设施建设中扮演着不可或缺的角色&#xff0c;虽然看似并不起眼但确实是城市规划中一个重要的组成部分。在城市规划建设之初都需要首先考虑排水系统的设计&#xff0c;而井盖作为排水系统的一个重要组成部分&#xff0c;一旦出现问题便会造成交通中断或者环境受影…

【洛谷 P1636】Einstein学画画 题解(图论+欧拉通路)

Einstein学画画 题目描述 Einstein 学起了画画。 此人比较懒~~&#xff0c;他希望用最少的笔画画出一张画…… 给定一个无向图&#xff0c;包含 n n n 个顶点&#xff08;编号 1 ∼ n 1 \sim n 1∼n&#xff09;&#xff0c; m m m 条边&#xff0c;求最少用多少笔可以画…

C#,《小白学程序》第十七课:随机数(Random)第四,移动平均值(Moving Average)的计算方法与代码

1 文本格式 /// <summary> /// 《小白学程序》第十七课&#xff1a;随机数&#xff08;Random&#xff09;第四&#xff0c;移动平均值的计算方法与代码 /// 继续学习数据统计&#xff0c;移动平均值的计算方法 /// 移动平均值就是一定步长内数值的平均值&#xff0c;用…

C#,《小白学程序》第十六课:随机数(Random)第三,正态分布的随机数的计算方法与代码

1 随机数的问题 用 C# Random 类生成的随机数是平均分布的。也就是各数据段的出现的次数差不多。彩票号码属于这种随机数。 而很多很多常见的随机数&#xff0c;比如&#xff1a;成绩&#xff0c;却是符合正态分布的。 因而很多时候需要生成符合正态分布规律的随机数。 2 文…

20年的大厂技术总监给云原生从业者的建议

云原生是一种构建和运行应用程序的方法&#xff0c;是一套技术体系和方法论。云原生的英文可拆解为Cloud和Native。Cloud表示应用程序位于云中&#xff0c;而不是传统的数据中心&#xff1b;Native表示应用程序设计之初就被考虑部署到云的环境&#xff0c;为云而生&#xff0c;…

micro_ros需要用到的hardware

我没有那么长的线啊&#xff0c;所以就用一个4块5的usb转串口看看 没有那么高档的开发板&#xff0c;就用主流的STM32F103C8T6试试看 这应该就是个仿真器了&#xff0c;一个字不认得都能够看的出来吧

集「才华」与「美貌」于一身的原型设计利器—摹客RP

文章目录 画原型做设计&#xff0c;用摹客RP就够了 初遇摹客再遇摹客RP摹客RP简介与注册摹客RP的突出亮点1️⃣拥有海量矢量图标&#xff0c;满足各种设计场景2️⃣打造高扩展性组件&#xff0c;打破传统组件编辑模式3️⃣海量摹客RP模板例子随意挑选4️⃣实现多人实时协同&…

【ArcGIS Pro微课1000例】0035:栅格影像拼接(dem高程数据)

本实验讲解在ArcGIS Pro中,栅格数据的两种拼接(镶嵌)方法,适用于遥感影像、DOM、DEM、DSM等常见栅格数据。 文章目录 一、加载实验数据二、栅格拼接工具1. 镶嵌2. 镶嵌至新栅格三、注意事项四、拓展阅读一、加载实验数据 加载配套实验数据中的0035.rar中的两个dem数据,如…

Vue项目实战之一----实现分类弹框效果

效果图 实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"js/vue.js"></script><!-- 引入样式 --><link rel"stylesheet&qu…