我是一名大学生,出于对互联网世界的好奇,在网上收集了各种信息资料,尝试过 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:如果你是有经验的电脑玩家,那么你可以不需要借助下面的文章,直接根据上面的简明摘要,开始配置了。
我以华为云的 HECS(云耀云服务器) 为例:
1 、打开 华为云 - 控制台 ,找到所购买的服务器。
2 、打开华为云服务器的安全组配置界面:
3 、开放以下端口(8888 、888 、80 、21 、20)以及一个自定义端口(12345)。
1 、打开 宝塔面板官网 ,下载 Windows Server 版的安装程序,解压后进行安装!
2 、宝塔面板安装完成之后,首次进入会弹出登录配置界面,如下:(附:面板使用教程)
3 、打开面板,通过账号密码首次登录面板之后,选择适合自己的套件(根据服务器的性能决定),然后选择 “一键安装” ,等待安装完成!
4 、安装完成之后,选择 “ 网站 ” ,然后删除自动生成的站点,创建新的站点
5 、打开浏览器,在URL地址栏输入 服务器的公网IP 进行查询,如果效果如下,则表示Web服务环境搭建完成!
End:到此,宝塔面板服务搭建完成!
1 、进入Node.JS官网,下载对应的Node.JS版本进行安装( 我以 Node.JS - v18.16.0 版本为例 )(附:Node.JS历史版本)
2 、通过命令node -v
检查 Node.JS 是否安装成功!
3 、通过命令npm -v
检查npm是否安装成功!
> 4 、在【资源管理器】中找到宝塔面板搭建的Web服务存放的文件路径。并在地址栏输入“CMD”,然后回车,打开DOS命令窗口。
3 、输入命令npm init -y
初始化项目。命令执行玩之后,可以看到,会生成一个名为“package.json”的配置文件
4 、基于自己的需求,对多余的文件进行删除或保留!
End:到此,API项目的初始化就已经完成!
1 、通过 NPM 安装以下三个 Node.JS 第三方模块(以下为局部安装命令):
a)、Express 模块 - 安装命令:npm install express
b)、Nodemon 模块 - 安装命令:npm install nodemon
c)、CORS 模块 - 安装命令:npm install cors
2 、全局安装(进行局部安装之后,全局安装即可省略!):
全局安装(express + nodemon )- 安装命令:npm install express nodemon -g
执行完成之后,会看到与 package.json 文件同级的目录下,会多出一个 node_modules 的文件夹,里面存放的是Node.JS第三方模块的依赖资源。
End:到此,所有的环境就已经配置完成!
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} 端口 ---------------------- `);
})
在DOS命令窗口输入以下任一命令,启动服务,开始监听指定端口!
node Server.js // 启动端口监听,一次性服务 nodemon Server.js // 启动端口监听,会自动检测服务器文件是否更新,并进行服务器重启!
End:到此,API接口的配置就结束了 ,接下来是测试接口的环节!
客户端 - 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>
在正在运行API接口的DOS命令窗口输入【快捷键】 Ctrl + C,即可终止运行!
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 . 有哪些办法能解决跨域问题?
有以下几种方法可以解决跨域问题:
- JSONP(JSON with Padding):JSONP 是一种利用
标签可以跨域加载资源的特性来实现跨域请求的方法。通过在请求中指定回调函数名,服务器返回的数据会被包裹在该函数调用中,从而可以在客户端通过回调函数来获取数据。
- CORS(Cross-Origin Resource Sharing):CORS 是一种现代化的跨域解决方案,通过在服务器端设置特定的响应头,允许浏览器跨域访问指定的资源。通常需要在服务器端设置
Access-Control-Allow-Origin
头部字段来指定允许访问的来源域名。- 代理服务器:可以通过在自己的服务器上设置一个代理服务器,将跨域请求转发到目标服务器上。客户端只需要与自己的服务器进行通信,而不直接与目标服务器进行跨域请求,从而规避了同源策略的限制。
- Nginx反向代理:可以通过配置Nginx服务器作为反向代理,在同一个域名下,不同路径下的请求转发到不同的目标服务器上,实现跨域请求。
- WebSocket协议:WebSocket 是一种全双工通信协议,它支持跨域通信。通过在服务器端进行设置,可以允许浏览器与其他域的 WebSocket 服务器进行跨域通信。
如果大家都看到了这里,我能够向大家要个赞吗,你们的点赞是我最大的动力!