You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js路由逻辑错误:无法匹配带id参数的请求及优化

Node.js SSR路由问题修复与代码优化

问题描述

在Node.js服务端渲染项目中,修复图片资源加载问题后,发现带id参数的请求无法进入对应处理分支,同时页面包含大量图片,需要修正逻辑错误并优化路由代码。

错误原因

路由判断顺序错误:当请求为/?id=xxx或/main?id=xxx时,第一个if条件(匹配/或/main路径)会优先触发,直接进入主页处理逻辑,导致带id参数的请求永远不会走到对应的分支。

修复与优化方案

  1. 调整路由判断顺序:优先检查请求是否携带id参数,再匹配主页路径,确保带参数的请求能被正确处理
  2. 提前解析数据库JSON:避免每次请求主页时重复解析JSON文件,提升性能
  3. 用path模块处理路径:替代字符串拼接,避免跨系统路径格式问题
  4. 完善404错误处理:增加默认分支,处理所有未匹配的请求
  5. 优化详情页链接生成:直接使用固定路径/movie?id=xxx,避免依赖当前请求路径,逻辑更清晰

修复后完整代码

const http = require("http");
const url = require("url");
const fs = require("fs");
const path = require("path");
const mimeTypes = require("mime-types");

// 提前解析数据库,避免每次请求重复解析
const movies = JSON.parse(fs.readFileSync(`${__dirname}/database/movies.json`, "utf-8"));
const cardTemplate = fs.readFileSync(`${__dirname}/templates/movieCard.html`, "utf-8");
const mainPageTemp = fs.readFileSync(`${__dirname}/templates/mainPage.html`, "utf-8");
// 假设存在电影详情页模板
const movieDetailTemp = fs.readFileSync(`${__dirname}/templates/movieDetail.html`, "utf-8");

const server = http.createServer((req, res) => {
  const parsedURL = url.parse(req.url, true);

  // 1. 优先处理带id参数的请求
  if (parsedURL.query.id) {
    console.log("处理电影详情请求");
    const movieId = parsedURL.query.id;
    const targetMovie = movies.find(movie => movie.id === movieId);
    
    if (!targetMovie) {
      res.writeHead(404, {"Content-Type": "text/html"});
      res.end("<h1>电影不存在</h1>");
      return;
    }

    // 渲染详情页模板
    let output = movieDetailTemp.replace(/{%MOVIENAME%}/g, targetMovie.title);
    output = output.replace(/{%IMAGE%}/g, `/public/${targetMovie.cover}`);
    output = output.replace(/{%DESCRIPTION%}/g, targetMovie.description);
    
    res.writeHead(200, {"Content-Type": "text/html"});
    res.end(output);
  } 
  // 2. 处理主页请求
  else if (parsedURL.pathname === "/" || parsedURL.pathname === "/main") {
    console.log("处理主页请求");
    res.setHeader("X-Content-Type-Options", "nosniff");
    res.writeHead(200, {"Content-Type": "text/html"});

    const latestPosts = movies.slice(0, 3);
    const cardsHtml = latestPosts
      .map(el => cardTemplateReplacor(cardTemplate, el))
      .join("");

    const output = mainPageTemp.replace(/{%POSTS%}/g, cardsHtml);
    res.end(output);
  } 
  // 3. 处理静态资源(图片等)
  else if (parsedURL.pathname.startsWith("/public/")) {
    console.log("处理静态资源请求");
    const resourcePath = path.join(__dirname, parsedURL.pathname);
    
    fs.readFile(resourcePath, (err, content) => {
      if (err) {
        res.writeHead(404, {"Content-Type": "text/html"});
        res.end("<h1>资源不存在</h1>");
      } else {
        const mimeType = mimeTypes.lookup(resourcePath);
        res.writeHead(200, {"Content-Type": mimeType || "application/octet-stream"});
        res.end(content);
      }
    });
  } 
  // 4. 处理404请求
  else {
    res.writeHead(404, {"Content-Type": "text/html"});
    res.end("<h1>页面不存在</h1>");
  }
});

const cardTemplateReplacor = function(template, card) {
  const imageLink = `/public/${card.cover}`;
  // 使用固定路径生成详情页链接,避免依赖当前路径
  const moviePageLink = `/movie?id=${card.id}`;
  let output = template.replace(/{%IMAGELINK%}/g, imageLink);
  output = output.replace(/{%MOVIENAME%}/g, card.title);
  output = output.replace(/{%MOVIELINK%}/g, moviePageLink);
  return output;
};

server.listen(8080, () => {
  console.log("服务器运行在8080端口");
});

额外说明

  • 新增了电影详情页模板的渲染逻辑(需确保templates/movieDetail.html存在,模板中包含{%MOVIENAME%}、{%IMAGE%}、{%DESCRIPTION%}等占位符)
  • 静态资源处理增加了默认MIME类型,避免无法识别类型的资源报错
  • 所有路径使用path.join拼接,兼容Windows和Linux系统

内容的提问来源于stack exchange,提问作者imanmoodi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 18:43:36