基于宝塔面板和Node.JS开发简单的API接口

为什么写这篇博客?

我是一名大学生,出于对互联网世界的好奇,在网上收集了各种信息资料,尝试过 N 种方法,在搭建服务器这方面也遇到很多问题,不过还好,经历过重重问题的考验,最终还是找到了通过最简单的方法搭建一个API接口的方法,所以想写下这篇博客。一是为了记录我的搭建经历;二是跟大家分享一下我搭建的一个经过,希望我的经历能帮助到大家,让对这方面有兴趣的人少走些弯路。如有什么不足的地方也还请大家帮忙指出,也希望大佬互喷!

这个页面解决什么问题?

这篇文章将通过 Node.JS 搭建一个简单的API接口,以满足在后续开发中对数据的一个存储需求!
PS:因为个人对数据内容的需求量不大,所以并没有涉及到数据库的来进行数据保存!

我需要掌握什么前置知识?

理论上,只要读者具有使用搜索引擎查找问题的能力,以及足够细心和耐心,照着教程一字一句地看,一步步地做,那么读者不需要任何前置知识。
当然,最基本的电脑维护操作,如对Windows系统的一些基本概念、,至少读者是要会的。

我需要准备什么?

搭建网站环境最基本要求是这样的:
1 、服务器(Windows Server系统)(我以华为云的服务器为例,配置:2H4G 3M)
2 、联网的台式/笔记本电脑(用于调试以及配置服务器以及代码)

PS:服务器并不是必需品,也可以在自己电脑中搭建Web服务环境,然后搭建API服务,具体的搭建步骤可以参考这篇文章。

准备就绪!

让我们首先来浏览一遍简明版的搭建流程,以便你时刻知道自己走到了哪一步,该干什么:

1 、开放服务器的端口
2 、安装宝塔面板,配置Web服务环境
3 、安装 Node.JS,进行项目初始化
4 、通过Node.JS配置 JavaScript 脚本运行环境
5 、配置接口处理事件(核心)
  • 了解Node.js的基本概念和语法
  • 了解Express框架的基本概念和使用
  • 设计API接口的URL和参数
  • 编写API接口处理函数
  • 通过CORS策略解决浏览器的跨域机制
  • 编写中间件处理请求参数(如body-parser等)
6 、启动API服务
7 、客户端请求测试
8 、停止API服务
9 、资源素材下载(附)

PS:如果你是有经验的电脑玩家,那么你可以不需要借助下面的文章,直接根据上面的简明摘要,开始配置了。

Step 1 . 开放服务器的端口

我以华为云的 HECS(云耀云服务器) 为例:

1 、打开 华为云 - 控制台 ,找到所购买的服务器。
2 、打开华为云服务器的安全组配置界面:
基于宝塔面板和Node.JS开发简单的API接口_第1张图片
3 、开放以下端口(8888 、888 、80 、21 、20)以及一个自定义端口(12345)。
基于宝塔面板和Node.JS开发简单的API接口_第2张图片
基于宝塔面板和Node.JS开发简单的API接口_第3张图片

Step 2 . 安装宝塔面板,配置Web服务环境

1 、打开 宝塔面板官网 ,下载 Windows Server 版的安装程序,解压后进行安装!

2 、宝塔面板安装完成之后,首次进入会弹出登录配置界面,如下:(附:面板使用教程)
基于宝塔面板和Node.JS开发简单的API接口_第4张图片
3 、打开面板,通过账号密码首次登录面板之后,选择适合自己的套件(根据服务器的性能决定),然后选择 “一键安装” ,等待安装完成!
基于宝塔面板和Node.JS开发简单的API接口_第5张图片
4 、安装完成之后,选择 “ 网站 ” ,然后删除自动生成的站点,创建新的站点
基于宝塔面板和Node.JS开发简单的API接口_第6张图片
5 、打开浏览器,在URL地址栏输入 服务器的公网IP 进行查询,如果效果如下,则表示Web服务环境搭建完成!
基于宝塔面板和Node.JS开发简单的API接口_第7张图片
End:到此,宝塔面板服务搭建完成!

Step 3 . 安装 Node.JS,进行项目初始化

1 、进入Node.JS官网,下载对应的Node.JS版本进行安装( 我以 Node.JS - v18.16.0 版本为例 )(附:Node.JS历史版本)
2 、通过命令 node -v检查 Node.JS 是否安装成功!
3 、通过命令 npm -v检查npm是否安装成功!
基于宝塔面板和Node.JS开发简单的API接口_第8张图片> 4 、在【资源管理器】中找到宝塔面板搭建的Web服务存放的文件路径。并在地址栏输入“CMD”,然后回车,打开DOS命令窗口。
基于宝塔面板和Node.JS开发简单的API接口_第9张图片
3 、输入命令 npm init -y 初始化项目。命令执行玩之后,可以看到,会生成一个名为“package.json”的配置文件
基于宝塔面板和Node.JS开发简单的API接口_第10张图片
4 、基于自己的需求,对多余的文件进行删除或保留!
基于宝塔面板和Node.JS开发简单的API接口_第11张图片
End:到此,API项目的初始化就已经完成!

Step 4 . 通过Node.JS配置 JavaScript 脚本运行环境

1 、通过 NPM 安装以下三个 Node.JS 第三方模块(以下为局部安装命令):
a)、Express 模块 - 安装命令:npm install express
b)、Nodemon 模块 - 安装命令:npm install nodemon
c)、CORS 模块 - 安装命令:npm install cors
基于宝塔面板和Node.JS开发简单的API接口_第12张图片
2 、全局安装(进行局部安装之后,全局安装即可省略!):
全局安装(express + nodemon )- 安装命令:npm install express nodemon -g
基于宝塔面板和Node.JS开发简单的API接口_第13张图片
执行完成之后,会看到与 package.json 文件同级的目录下,会多出一个 node_modules 的文件夹,里面存放的是Node.JS第三方模块的依赖资源。

End:到此,所有的环境就已经配置完成!

Step 5 . 配置接口处理事件(核心)

PS:由于个人对接口的需求不一样,所以在这我就通过一段代码演示一些基础的功能!具体的需求还得自己去学习贯通,不过其基本语法使用的还是JavaScript,对于前端开发者来说学习成本还是比较低的!

服务器端 - 处理服务(实例代码比较简单,展示的都是一些比较常用的方法,具体的使用场景以及需求得根据实际情况进行开发):

1 、在与package.json文件同级的目录下创建一个JavaScript文件,如(Server.js),代码内容如下:

const express = require("express");        // 引入Express框架

const path = require("path")    // 引入path模块

const fs = require("fs")        // 引入fs模块

// const cors = require("cors")        // 引入cors模块

const http = require('http');

const querystring = require('querystring'); // 引入Node.js内置的querystring模块

const bodyParser = require("body-parser");   // 引入body-parser模块

const { json } = require("body-parser");
const { send } = require("process");
const { url } = require("inspector");

let app = express();    // 项目的顶级对象

const PORT = 12345;      // 设置API调用的接口

// 两个配置项,bodyParser功能添加到app项目中
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())


// 添加 CORS 头部信息,解决跨域问题
app.use(function (req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
  next();
});

/* -------------------------- “/” - 接口配置 - GET -------------------------- */
// 【GET 请求】app.get(可以处理的请求路径,处理函数);
// 【执行条件】当浏览器访问这个路径的时候,这个函数就会执行
app.get("/", (req, res) => {
  let client = {
    // 记录当前时间  
    Time : new Date().getFullYear() + "-" + (new Date().getMonth() + 1) + "-" + new Date().getDate() + " " + new Date().getHours() + ":" + new Date().getMinutes() + ":" + new Date().getSeconds(),
    // 记录发送请求的客户端 IP 地址  
    ClientIP : req.connection.remoteAddress.replace('::ffff:', ''),
    // 记录Get请求的查询值
    QueryValue : req.query,
    // 记录设备的详细信息  
    ClientDevice_Detail : req.headers['user-agent'],
    // 记录简要设备信息  
    ClientDevice_Easy : /\(([^)]+)\)/.exec(req.headers['user-agent'])[1]
  };

  // 服务器端 - 请求信息提醒
  console.log(`${client.Time} 】 终端 (IP:${client.ClientIP} )通过“/”向服务器发送了GET请求!(设备:${client.ClientDevice_Easy}`);

  res.send(client); // 返回数据给请求终端  
});


/* -------------------------- “/” - 接口配置 - POST -------------------------- */
// 【POST 请求】app.post(可以处理的请求路径,处理函数);
// 【执行条件】当浏览器访问这个路径的时候,这个函数就会执行
app.post("/", (req, res) => {

  // 服务器 - 请求信息提醒!
  console.log(`${new Date().getFullYear()}-${new Date().getMonth() + 1}-${new Date().getDate()}  ${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()} 】 终端 (IP:${req.connection.remoteAddress.replace('::ffff:','')} )通过“/”向服务器发送了POST请求!`);

  let ClientText = req.body;    // 获取客户端发送过来的数据

  // 拼接目标文件路径
  let filePath = path.join(__dirname, "DataFile", "Data.json");
  // 获取目标文件内容
  let TextContent = fs.readFileSync(filePath, "utf8")

  let TempObj = JSON.parse(TextContent);    // 转换数据类型 ( String -> Obj )

  TempObj.Previous = TempObj.Record;    // 覆盖原来的记录
  TempObj.Record = ClientText.Text          // 新增记录

  // 将新数据重新写入文件
  fs.writeFileSync(filePath,JSON.stringify(TempObj))

  res.send(TempObj)   // 返回数据给请求端
})


/* -------------------------- “/Demo” - 接口配置 - GET -------------------------- */
// 【GET 请求】app.get(可以处理的请求路径,处理函数);
// 【执行条件】当浏览器访问这个路径的时候,这个函数就会执行
app.get("/Demo", (req, res) => {
  
  // 服务器 - 请求信息提醒!
  console.log(`${new Date().getFullYear()}-${new Date().getMonth() + 1}-${new Date().getDate()}  ${new Date().getHours()}:${new Date().getMinutes()}:${new Date().getSeconds()} 】 终端 (IP:${req.connection.remoteAddress.replace('::ffff:','')} )通过“/Demo”向服务器发送了Get请求!`);

  res.send(`【/Demo】API接口 - 数据调用成功!`); // 返回数据给请求终端  
});


// 启动端口监听
app.listen(PORT, () => {
  console.log(`---------------------- API 服务已启动,正在监听 ${PORT} 端口 ---------------------- `);
})

2 、目录结构:
基于宝塔面板和Node.JS开发简单的API接口_第14张图片


Step 6 . 启动API服务

在DOS命令窗口输入以下任一命令,启动服务,开始监听指定端口!

node Server.js  // 启动端口监听,一次性服务
nodemon Server.js 	// 启动端口监听,会自动检测服务器文件是否更新,并进行服务器重启!

End:到此,API接口的配置就结束了 ,接下来是测试接口的环节!

Step 7 . 客户端请求测试

客户端 - API请求实例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>API - Test</title>
    <script src="https://code.jquery.com/jquery-3.6.4.min.js"></script>
</head>
<body>
    <h1>华为云 - 云耀云服务器</h1>
    <button id="Btn_Get">【jQuery】API 测试 - Get请求</button>
    <button id="Btn_Post">【jQuery】API 测试 - Post请求</button>
    <br><br>
    <button id="Ajax_Get">【Ajax】API 测试 - Get请求</button>
    <button id="Ajax_Post">【Ajax】API 测试 - Post请求</button>
    <br><br>
    <button id="SecondAPI">"/Demo"入口 - jQuery的GET请求</button>
    <br><br>
    <button id="CompressionTest">-------- 服务器 - 抗压测试 -------- </button>
    <pre id="show">代码展示,等待获取中…………</pre>
    <script>
        // 【jQuery】向服务器发送GET请求
        Btn_Get.onclick = function(){
            $.ajax({
                url: 'http://…………:12345',
                method: 'GET',
                data: {Title: 'Hello!', Text: "你好!"},
                success: function(response) {
                    console.log('请求成功', response);
                    document.querySelector("#show").innerHTML = JSON.stringify(response, null, 4);
                },
                error: function(error) {
                    console.log('请求出错', error);
                    document.querySelector("#show").innerHTML = "GET - 请求失败!";
                }
            });
        }

        // 【jQuery】向服务器发送POST请求
        Btn_Post.onclick = function(){
            let Text = window.prompt("请输入新记录的值 :")
            $.ajax({
                url: 'http://…………:12345',
                method: 'POST',
                data: {name: '温Wen', Text: Text},
                success: function(response) {
                    console.log('请求成功', response);
                    document.querySelector("#show").innerHTML = JSON.stringify(response, null, 4);
                },
                error: function(error) {
                    console.log('请求出错', error);
                    document.querySelector("#show").innerHTML = "POST - 请求失败!";
                }
            });
        }

        // 【Ajax】- Get请求
        Ajax_Get.onclick = function(){
            var xhr = new XMLHttpRequest();
            xhr.open('GET', 'http://…………:12345?Title=Hello!&Text=你好,我是温先森!');
            xhr.onload = function() {
                if (xhr.status === 200) {
                    console.log('请求成功', xhr.response);
                    document.querySelector("#show").innerHTML = JSON.stringify(JSON.parse(xhr.response),null,4);
                } else {
                    console.log('请求出错');
                    document.querySelector("#show").innerHTML = "GET - 请求失败!";
                }
            };
            xhr.onerror = function() {
                console.log('请求出错');
                document.querySelector("#show").innerHTML = "GET - 请求失败!";
            };
            xhr.send();
        }

        // 【Ajax】- Post请求
        Ajax_Post.onclick = function(){
            let Text = window.prompt("请输入新记录的值:");
            let xhr = new XMLHttpRequest();
            xhr.open('POST', 'http://…………:12345', true);
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            xhr.onreadystatechange = function() {
                if (this.readyState === XMLHttpRequest.DONE && this.status === 200) {
                    console.log('请求成功', this.responseText);
                    document.querySelector("#show").innerHTML = JSON.stringify(JSON.parse(this.responseText), null, 4);
                } else if (this.readyState === XMLHttpRequest.DONE) {
                    console.log('请求出错');
                    document.querySelector("#show").innerHTML = "POST - 请求失败!";
                }
            };
            xhr.onerror = function() {
                console.log('请求出错');
                document.querySelector("#show").innerHTML = "POST - 请求失败!";
            };
            xhr.send('name=温Wen&Text='+encodeURIComponent(Text));
        }

        // "/Demo"入口 - jQuery的GET请求
        SecondAPI.onclick = function(){
            $.ajax({
                url: 'http://…………:12345/Demo',
                method: 'GET',
                data: {Title: 'Hello!', Text: "你好!"},
                success: function(response) {
                    console.log('请求成功', response);
                    document.querySelector("#show").innerHTML = JSON.stringify(response, null, 4);
                },
                error: function(error) {
                    console.log('请求出错', error);
                    document.querySelector("#show").innerHTML = "GET - 请求失败!";
                }
            });
        }


        // 服务器 - 抗压测试
        CompressionTest.onclick = function(){
            var count = 0;
            for(let i = 0 ; i < 100 ; i++ ){
                document.querySelector("#show").innerHTML = `${count++}`;
                $.ajax({
                    url: 'http://110.41.0.15:12345/',
                    method: 'GET',
                    async: true, // 将 async 设置为 false
                    success: function(response) {
                        console.log('请求成功', response);
                        document.querySelector("#show").innerHTML = response;
                    },
                    error: function(error) {
                        console.log('请求出错', error);
                        document.querySelector("#show").innerHTML = "GET - 请求失败!";
                    }
                });
            }
            document.querySelector("#CompressionTest").innerHTML = ` - - - - - 测试结束 - - - - - `;  
        }
    </script>
</body>
</html>

请求结果示例:
基于宝塔面板和Node.JS开发简单的API接口_第15张图片

Step 8 . 停止API服务

在正在运行API接口的DOS命令窗口输入【快捷键】 Ctrl + C,即可终止运行!

基于宝塔面板和Node.JS开发简单的API接口_第16张图片

Step 9 . 资源素材下载(附)

1 、服务器端 & 客户端请求测试 - 源码下载:点击下载(蓝奏云)

相关答疑

Question 1 . 可以选择哪些端口号作为我服务器的端口

在使用Node.js搭建API服务时,端口号的选择范围是从0到65535。然而,在实际应用中,常用的端口号范围是1024到49151之间。这是因为0到1023之间的端口号通常被系统保留用于特定的服务,而49152到65535之间的端口号归类为动态或私有端口,可以用于自定义应用程序。所以在选择端口号时,最好避开这些保留端口和常用端口,以免与现有服务冲突。通常推荐选择大于1024且未被占用的端口号

Question 2 . 为什么配置好宝塔面板,在浏览器 通过服务器公网 IP 地址进行访问会显示 Nigex 服务?

因为自动生成的站点域名填写的不对,需要修改成自己服务器的公网IP ,或者把自动生成的站点 删掉,自己建一个新的站点。

Question 3 . 有其他测试接口的方法吗 ?

有,不一定得根据第7步进行测试,还可以使用Postman工具进行测试,但是得注意跨域问题,在使用Postman工具进行测试的时候,不会出现跨域问题,测试环境比较理想!。

Question 4 . 什么是跨域?

Web 浏览器遵循同源策略(Same-Origin Policy),该策略要求不同源(即协议、域名、端口号有且只有一个不同)的网页之间默认不能相互访问彼此的资源。这是为了保护用户的安全和隐私。
简单点说就是在浏览器中,当一个网页的 JavaScript 代码向另一个域名的资源发送请求时,如果这个请求的目标域名与当前网页的域名不同,就会出现跨域问题

Question 5 . 有哪些办法能解决跨域问题?

有以下几种方法可以解决跨域问题:

  1. JSONP(JSON with Padding):JSONP 是一种利用

你可能感兴趣的:(node.js,后端,前端,javascript,ajax,windows,web)