本文旨在记录 express 在个人前端工作上的一些应用,用于快速组建一个可测试和验证的最小 demo,方便定位问题和验证解决方案。(注: 下列代码的使用的 express 版本为 ^4.17.1)
获取 ip
首先很多情况下,我们无法使用 localhost 去访问 api,比如在 android 的测试机上测试,如果每次都通过命令去获取,然后在一大堆繁杂的信息中获取 ip 很麻烦,可以直接使用 node 的 os
api
const os = require("os");
const express = require("express");
const app = express();
app.get("/test", (req, res) => {
res.json({ greeting: "Hello world!" });
});
const getIPAddress = () => {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
if (iface.family === "IPv4" && !iface.internal) {
return iface.address;
}
}
}
throw new Error("No valid IP address found.");
};
const ipAddress = getIPAddress();
const port = 8020;
app.listen(port, () => {
console.log(`Server is listening at http://${ipAddress}:${port}`);
});
文件服务
以前有个需求,用户滑动验证后才能 call api,需要用 webview 渲染个 html,为了避免修改需要重新出 build 上线,决定将 html 放服务器上;html 由前端提供,由于需要频繁修改,有时仅仅只是加个 log,都需要交给 BE 放到文件服务器,沟通成本不低,所以搞个文件服务配合前面的自动获取 ip 可以很方便地实现开发
在项目根目录上建立一个 public 文件夹,里面根据需要可以建 images、codes、fonts 之类,命名单复数最好统一
const app = express();
app.use(express.static("public"));
app.get("/public/images/*", function (req, res) {
res.sendFile(__dirname + "/" + req.url);
console.log("Request for " + req.url + " received.");
});
app.get("/public/code/*", function (req, res) {
res.sendFile(__dirname + "/" + req.url);
console.log("Request for " + req.url + " received.");
});
app.get("/public/fonts/*", function (req, res) {
res.sendFile(__dirname + "/" + req.url);
console.log("Request for " + req.url + " received.");
});
headers
header 问题是很常见的,无论是测试前后端交互参数携带,还是某些文件不能工作,可能都涉及到 header。我曾经遇到音频无法在 iOS 播放,后来发现是 header 问题,把音频下载后放在服务器上然后删除某个 header 就能播放了
app.all("/*", (req, res, next) => {
// 查看所有请求的 headers
console.log("All Headers: ", req.headers);
// 全局设置 Header
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "X-Requested-With");
next();
});
app.get("/test", (req, res) => {
// 查看 Header
console.log("Test Headers: ", req.headers);
// 单独设置 Header
res.header("Test-Header", "Test").json({ greeting: "Hello world!" });
});
跨域
有时 api 用于页面测试开发也是很常见的,那么就需要解决跨域问题,复杂情况可以使用 cors
中间件处理,简单地可以设置 Header 来解决问题
if (["http://localhost:5173"].includes(req.headers.origin)) {
res.header("Access-Control-Allow-Origin", req.headers.origin);
}
不过,不放上公网的话,还可以更简单点
res.header("Access-Control-Allow-Origin", "*");
Cookies
Cookie 也常用于前后端交互,使用 cookie-parser
可以方便地解析参数,express 同时支持增删改查 cookie
const express = require("express");
const cookieParser = require("cookie-parser");
const app = express();
app.use(cookieParser());
app.get("/cookies-demo", (req, res) => {
// 通过 cookie-parser 解析,可以查看到 key-value 格式的对象
console.log("cookies: ", req.cookies);
res
.cookie("randomNum", `${Math.random()}`, {
httpOnly: true,
sameSite: "strict",
secure: true,
// 如果 path 为 / 匹配任何路由,为 /api 则只匹配如 /api/*** 开头的路由
path: "/",
})
.cookie("fixedNum", "1996")
.json({
greeting: "Hello world",
});
});