From 5c462a4d0985230f334cc580aec304fb4314372f Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Mon, 17 Aug 2026 15:41:36 +0800 Subject: [PATCH] =?UTF-8?q?fix(server):=20=E6=94=B9=E7=94=A8=20Express=205?= =?UTF-8?q?=20+=20path-to-regexp=20v7=20=E5=85=BC=E5=AE=B9=E7=9A=84?= =?UTF-8?q?=E9=80=9A=E9=85=8D=E5=86=99=E6=B3=95=EF=BC=8C=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E8=B7=AF=E7=94=B1=E5=90=AF=E5=8A=A8=E5=B4=A9=E6=BA=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Express 5 内置的 path-to-regexp v7 不再支持裸 '*',也不支持 自定义正则 '.*'(会报 Missing parameter name)。Express 5 官方兼容的单段全通写是 ':name(*)',并且路由注册会在 app 启动 第一时间完成(出错会直接崩)。 同时为了兼容旧 URL 行为,保留 express.static 前置挂载 + 显式 app.get 后备两条路径,因为 Audio 模块可能需要带 Cache-Control / Range / Content-Type 等头的 custom sendBinaryFile 处理(例如 station 动态裁剪音频),所以不能直接用 static 替代。 修复 7 条路由: /media/audio/general/:path(*) /media/audio/beep/:path(*) /media/audio/music/:path(*) /media/audio/voice/:path(*) /media/audio/line/:path(*) /media/audio/station/:path(*) /media/temp/:path(*) 参数解码加 decodeURIComponent(),兼容中文/空格文件名。 客户端 bump v1.0.101 -> v1.0.102 --- CloudServer/server.js | 38 ++++++++++++++++++++++---------------- station_broadcast.lua | 2 +- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/CloudServer/server.js b/CloudServer/server.js index 4b102bf..7c67dd1 100644 --- a/CloudServer/server.js +++ b/CloudServer/server.js @@ -148,44 +148,50 @@ function safeRelativeToBase(baseDir, relativePath) { return full; } -app.get('/media/audio/general/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.use('/media/audio/general', express.static(getBeepAudioDirs(), { fallthrough: true })); +app.use('/media/audio/beep', express.static(getBeepAudioDirs(), { fallthrough: true })); +app.use('/media/audio/music', express.static(audioMusicDir, { fallthrough: true })); +app.use('/media/audio/voice', express.static(audioVoiceDir, { fallthrough: true })); +app.use('/media/audio/line', express.static(audioLineDir, { fallthrough: true })); +app.use('/media/audio/station', express.static(audioStationDir, { fallthrough: true })); +app.use('/media/temp', express.static(tempBroadcastDir, { fallthrough: true })); + +app.get('/media/audio/general/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const candidates = getBeepAudioDirs().map(dir => safeRelativeToBase(dir, rel)).filter(Boolean); sendBinaryFileFromCandidates(res, candidates); }); -app.get('/media/audio/beep/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.get('/media/audio/beep/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const candidates = getBeepAudioDirs().map(dir => safeRelativeToBase(dir, rel)).filter(Boolean); sendBinaryFileFromCandidates(res, candidates); }); -app.get('/media/audio/music/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.get('/media/audio/music/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const full = safeRelativeToBase(audioMusicDir, rel); if (!full) return res.status(404).end(); sendBinaryFile(res, full); }); -app.get('/media/audio/voice/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.get('/media/audio/voice/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const full = safeRelativeToBase(audioVoiceDir, rel); if (!full) return res.status(404).end(); sendBinaryFile(res, full); }); -app.get('/media/audio/line/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.get('/media/audio/line/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const full = safeRelativeToBase(audioLineDir, rel); if (!full) return res.status(404).end(); sendBinaryFile(res, full); }); - -app.get('/media/audio/station/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.get('/media/audio/station/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const full = safeRelativeToBase(audioStationDir, rel); if (!full) return res.status(404).end(); sendBinaryFile(res, full); }); - -app.get('/media/temp/:relPath(.*)', (req, res) => { - const rel = req.params.relPath || ''; +app.get('/media/temp/:path(*)', (req, res) => { + const rel = decodeURIComponent(req.params.path || ''); const full = safeRelativeToBase(tempBroadcastDir, rel); if (!full) return res.status(404).end(); sendBinaryFile(res, full); diff --git a/station_broadcast.lua b/station_broadcast.lua index d455c29..2dd1ddc 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1,6 +1,6 @@ -- 1. Configuration & Constants -local APP_VERSION_TEXT = "v1.0.101" +local APP_VERSION_TEXT = "v1.0.102" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group",