React应用通过多层服务器代理在Iframe中加载Application-2时出现404错误的排查及优化方案咨询
我现在遇到了一个棘手的问题:有两个React应用,Application-1需要通过iframe打开Application-2。Application-2本身可以直接访问,但通过Application-1的iframe访问时,必须经过多层服务器跳转,具体路径是这样的:
Application-1 ----> Express-Server-1(负责提供Application-1服务并转发Application-2的请求) ----> Express-Server-2(代理中转) -------> Express-Server-3(提供Application-2服务)-----> Application-2
目前的状况是,直接访问Application-2完全没问题,但通过Application-1的iframe访问时,就会触发404错误。下面我把各个服务器的配置代码和错误信息贴出来,想请教大家怎么解决这个404问题,同时也想问问有没有更合适的方案来实现这种多层服务器跳转的需求(因为有认证限制,不能让Application-1直接访问Application-2)。
Server-3(提供Application-2服务的核心配置)
这是运行在Server-3上的app.js,负责提供Application-2的服务:
const createError = require("http-errors"); const express = require("express"); const cors = require('cors') const path = require("path"); const fs = require("fs"); const cookieParser = require("cookie-parser"); // Server-static middleware const { appLogger, expressLogger, expressErrorLogger, } = require("./lib/logger"); const {corsOptionsDelegate} = require("./routes/corsDelegate"); const app = express(); app.disable("x-powered-by"); app.options('*', cors()); // serves static pages app.use("/application-2/static", express.static(path.join(__dirname, "public"))); // view engine setup app.set("views", path.join(__dirname, "views")); app.set("view engine", "jade"); app.use(express.json()); app.use(express.urlencoded({extended: false})); app.use(expressLogger); app.use(expressErrorLogger); app.use(cookieParser()); app.use( express.static(path.join(__dirname, ".", "webapp")), (req, res, next) => { try { decodeURIComponent(req.url); return next(); } catch (err) { return res.status(400).json({message: "Invalid request"}); } } ); const managementRouter = require("./routes/management"); app.use("/application-2/management", managementRouter); // serves the application-2 app app.use("/application-2", express.static(path.join(__dirname, ".", "webapp"))); // connect to the "src/routes" directory const routersPath = path.join(__dirname, "routes/v1"); // read all files in the "/src/routers" directory fs.readdirSync(routersPath).forEach((file) => { if (file.endsWith(".js")) { // dynamically import the router module const routerModule = require((path.join(routersPath, file).replace(".js",""))); // register the router app.use(routerModule); } }); app.get("/application-2/unauthorized", cors(corsOptionsDelegate), function (req, res, next) { res.status(403); res.sendFile(path.resolve(__dirname, ".", "views", "unauthorized.html")); }); // catch 404 and forward to error handler app.use(function (req, res, next) { // ERROR is happening here line 104 next(createError(404)); }); // error handling app.use(function (err, req, res, next) { // set locals, only providing error in development res.locals.message = err.message; res.locals.error = req.app.get("env") === "development" ? err : {}; // render the error page res.status(err.status || 500); res.render("error", {title: "ABC Images | application Search"}); }); module.exports = app;
Server-1(处理Application-1的iframe请求,转发到Server-2)
当Application-1打开iframe时,会向Server-1的/application-search路径发起请求,对应的代理配置如下:
app.use("/application-search", createProxyMiddleware({ target: "http://localhost:9012", changeOrigin: true, logLevel: 'debug', pathRewrite: (path, req) => { // Extract the query string from the original URL const queryString = req.url.split('?')[1] || "11x"; // Rewrite the path to include the query string return `/?${queryString}`; }, onProxyReq: (proxyReq, req, res) => { let cookieArray = []; try { // Split the cookies into an array and log them const cookies = req.headers.cookie || ""; cookieArray = cookies.split(';').map(row => { return row.trim(); }); } catch (error) { console.error('Error processing cookies:', error); } //const tokenCookie = cookieArray.find(row => row.startsWith('ckns_pp_id=')) || ""; const tokenValue = tokenCookie.split('=')[1].trim(); // Add custom headers if needed proxyReq.setHeader('Authorization', `Bearer ${tokenValue}`); } }));
Server-2(中转Server-1的请求到Server-3)
Server-2收到Server-1的请求后,会转发到提供Application-2的Server-3,配置如下:
app.use("/", createProxyMiddleware({ target: "https://xxx.co.uk/application-2", changeOrigin: true, logLevel: 'debug', pathRewrite: (path, req) => { // Extract the query string from the original URL const queryString = req.url.split('?')[1] || "11x"; // Rewrite the path to include the query string return `/?${queryString}`; }, onProxyReq: (proxyReq, req, res) => { // Add the authorization header const bearerToken = req.headers['authorization'] || ""; proxyReq.setHeader('Authorization', bearerToken); }, onProxyRes: (proxyRes, req, res) => { console.log(`⬅️ Response from Server-3: ${proxyRes.statusCode} for ${req.url}`); } }));
错误信息
现在通过Application-1的iframe加载Application-2时,会返回404错误,具体错误日志如下:
404 NotFoundError: Not Found at /Users/abc01/projects/application-2/server/app.js:104:10
我目前使用的是createProxyMiddleware来实现请求转发,想请教各位:有没有更合适的方案来满足这种多层跳转的需求?同时也希望能找到解决当前404问题的办法。
备注:内容来源于stack exchange,提问作者Umair_007

