使用Express Router代理非CORS资源时出现请求路径重复问题
问题根因
你遇到的路径重复问题完全是http-proxy-middleware(以下简称hpm)的默认配置逻辑导致的,和使用场景无关,hpm完全支持这种动态代理场景:
- hpm的
router配置本质是动态替换请求的目标源(协议+域名+端口部分),默认会自动把原请求的完整路径拼接到你router返回的地址后面。你现在在router的返回值里已经手动拼接了完整的目标资源路径,hpm又额外拼接了一次原请求路径,就出现了路径重复的问题。 - 另外你当前拆分路径的逻辑也存在边界隐患,比如目标域名后没有子路径时会切出多余的斜杠。
解决方案
有两种常用的修复方式,任选其一即可:
方案1:router仅返回目标源,用pathRewrite处理路径
这是更符合hpm设计规范的写法,逻辑更清晰:
const express = require('express') const { createProxyMiddleware } = require('http-proxy-middleware') const app = express() const PORT = 3000 const HOST = '0.0.0.0' app.get('/info', (req, res, next) => { res.send('Proxy is up.'); }) // Proxy endpoint app.use('/https', createProxyMiddleware({ target: "https://dummy.invalid", // 随便填个合法格式的地址即可,router会将其替换 router: req => { // 只提取目标域名,返回协议+域名的源地址即可 const hostname = req.path.split("/https/")[1].split("/")[0] return `https://${hostname}` }, changeOrigin: true, pathRewrite: (path, req) => { // 把路径前面的 /https/域名 部分删掉,只保留后面的资源路径 const hostname = path.split("/https/")[1].split("/")[0] return path.split(`/https/${hostname}`)[1] || '/' } })) app.listen(PORT, HOST, () => { console.log(`Starting Proxy at ${HOST}:${PORT}`); })
方案2:保留router返回完整地址,关闭自动路径拼接
如果你不想改现有router的拼接逻辑,只要加一个prependPath: false配置,关掉hpm自动拼接原路径的行为即可:
// Proxy endpoint app.use('/https', createProxyMiddleware({ target: "incoming", router: req => { const protocol = 'https' const hostname = req.path.split("/https/")[1].split("/")[0] const path = req.path.split(hostname)[1] console.log(`returning: ${protocol}, ${hostname}, ${path}`) return `${protocol}://${hostname}/${path}` }, changeOrigin: true, prependPath: false, // 核心配置:禁止自动拼接原请求路径 // 可选补充:如果目标资源有重定向,可加以下配置避免重定向跳转到原地址绕过代理 autoRewrite: true, hostRewrite: true }))
补充优化建议
如果需要同时支持http和https的资源代理,可以把匹配规则改成app.use(['/http', '/https'], ...),在router里根据路径前缀动态取协议即可。
内容的提问来源于stack exchange,提问作者cubap
相关产品推荐
相关产品推荐

