如何在Express控制器中调用document/redirect API并实现页面重定向
问题
原本通过HTML表单调用http://test/Integration.htm的document/redirect API,现在要在Express控制器里实现相同逻辑,流程是:前端→Express控制器→调用外部API→重定向前端页面。
试写了下面的Express控制器代码但没成功,尝试返回自定义HTML还碰到CORS错误,而且因为安全原因没法在前端直接实现,求正确的Express实现方案。
export const ssoHandler: any = async (req: Request, res: Response) => { const formData = new URLSearchParams(); const clientCandidateId = req.query.clientCandidateId as string; formData.append('TEST_VALUE', clientCandidateId); const response = await axios({ url: `${config.host}`, headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST', data: formData, }); res.write(response.data) };
解决方案
核心问题是你没正确处理外部API的重定向响应,反而直接返回了响应内容。下面给两个可行的实现方案:
方案1:转发外部API的重定向地址
如果外部API返回3xx重定向状态码,直接提取它的Location响应头,让Express给前端返回重定向指令:
import axios from 'axios'; import { Request, Response } from 'express'; import config from './config'; // 替换成你的配置文件路径 export const ssoHandler = async (req: Request, res: Response) => { try { const clientCandidateId = req.query.clientCandidateId as string; if (!clientCandidateId) { return res.status(400).send('缺少clientCandidateId参数'); } const formData = new URLSearchParams(); formData.append('TEST_VALUE', clientCandidateId); // 禁止axios自动跟随重定向,拿到原始的重定向响应 const response = await axios({ url: `${config.host}/document/redirect`, // 确保API路径正确,原需求是document/redirect headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, method: 'POST', data: formData, maxRedirects: 0, validateStatus: (status) => status >= 200 && status < 400, // 允许3xx状态码 }); // 处理重定向 if (response.status >= 300 && response.status < 400) { const redirectUrl = response.headers.location; if (redirectUrl) { return res.redirect(redirectUrl); } } // 若没有重定向,返回API响应内容 res.send(response.data); } catch (error) { console.error('调用外部API失败:', error); res.status(500).send('内部服务器错误'); } };
方案2:返回自动提交的表单(彻底解决CORS)
如果外部API的重定向需要保留会话上下文(比如Cookie),直接转发地址可能失效。这时候可以返回一个自动提交的HTML表单,让浏览器直接和外部API交互,完全规避CORS问题,逻辑和原HTML表单一致:
import { Request, Response } from 'express'; import config from './config'; export const ssoHandler = async (req: Request, res: Response) => { try { const clientCandidateId = req.query.clientCandidateId as string; if (!clientCandidateId) { return res.status(400).send('缺少clientCandidateId参数'); } // 生成自动提交的表单HTML,浏览器加载后会自动提交到外部API const autoSubmitForm = ` <!DOCTYPE html> <html> <body> <form id="ssoForm" method="POST" action="${config.host}/document/redirect"> <input type="hidden" name="TEST_VALUE" value="${clientCandidateId}"> </form> <script> document.getElementById('ssoForm').submit(); </script> </body> </html> `; res.setHeader('Content-Type', 'text/html'); res.send(autoSubmitForm); } catch (error) { console.error('生成跳转表单失败:', error); res.status(500).send('内部服务器错误'); } };
关键注意点
- 要确保
config.host包含完整的API路径,比如http://test/Integration.htm加上/document/redirect,根据实际情况调整。 - 必须做参数校验,比如检查
clientCandidateId是否存在,避免无效请求。 - 方案2更贴近原HTML表单的逻辑,能保留会话信息,同时彻底解决CORS问题,推荐优先尝试。
内容的提问来源于stack exchange,提问作者Ahmed Ahmed Sayed
相关产品推荐
相关产品推荐

