express 在个人前端工作上的一些应用

39 阅读2分钟

本文旨在记录 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",
    });
});