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

如何用Node.js Express的Rendertron中间件重定向至原Angular应用

解决Rendertron中间件转发非Bot请求到原应用的问题

核心问题分析

你的代码存在两个关键问题:

  1. 固定请求地址丢失用户实际请求路径:当前fetch直接请求固定地址,没有携带用户访问的具体路由(比如/about),导致原应用无法返回对应页面。
  2. 仅处理GET请求且未完整传递请求/响应信息:只实现了app.get('*'),忽略了POST/PUT等方法;同时没有传递原请求的headers、body,也未将原应用的响应头(如Content-Type、Cache-Control等)返回给客户端,导致页面样式、资源加载失败。

修复方案

1. 转发所有HTTP方法的请求

使用app.all('*')替代app.get('*'),覆盖所有请求方法(GET/POST/PUT/DELETE等)。

2. 动态拼接目标请求地址

将用户请求的path拼接至原应用地址后,确保请求对应路由。

3. 完整传递请求信息

转发原请求的headers、method、body(针对非GET请求)到原应用。

4. 完整返回响应信息

将原应用的响应头、状态码、响应体完整返回给客户端,确保页面正常渲染。

完整修改后的代码

const express = require('express');
const app = express();
const rendertron = require('rendertron-middleware');
const PORT = process.env.PORT || 8080;
const fetch = require('node-fetch');
const https = require('https');

const httpsAgent = new https.Agent({
  rejectUnauthorized: false,
});
const bots = [
  'googlebot',
  'baiduspider',
  'bingbot',
  'embedly',
  'facebookexternalhit',
  'linkedinbot',
  'outbrain',
  'pinterest',
  'quora link preview',
  'rogerbot',
  'showyoubot',
  'slackbot',
  'twitterbot',
  'vkShare',
  'W3C_Validator',
  'whatsapp',
];

const BOT_UA_PATTERN = new RegExp(bots.join('|'), 'i');

// 解析POST/PUT等请求的body
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// Rendertron中间件:仅处理Bot请求
app.use(rendertron.makeMiddleware({
  proxyUrl: 'https://render-tron.appspot.com/render',
  userAgentPattern: BOT_UA_PATTERN,
  injectShadyDom: true
}));

// 转发所有非Bot请求到原Angular应用
app.all('*', async (req, res) => {
  res.set('Vary', 'User-Agent');
  
  try {
    // 拼接目标地址:原应用地址 + 用户请求的路径
    const targetUrl = `https://kitten-corner.glitch.me${req.path}`;
    
    // 构建fetch选项:传递原请求的方法、headers、body
    const fetchOptions = {
      method: req.method,
      agent: httpsAgent,
      headers: {
        // 复制原请求headers,排除host等可能冲突的字段
        ...req.headers,
        host: new URL('https://kitten-corner.glitch.me').host
      },
      // 非GET请求传递body
      body: req.method !== 'GET' ? JSON.stringify(req.body) : undefined
    };
    
    // 请求原应用
    const response = await fetch(targetUrl, fetchOptions);
    
    // 传递原应用的响应头
    for (const [key, value] of response.headers.entries()) {
      res.setHeader(key, value);
    }
    
    // 设置响应状态码并返回响应体
    res.status(response.status);
    const body = await response.text();
    res.send(body);
  } catch (error) {
    console.error('转发请求失败:', error);
    res.status(500).send('服务器内部错误');
  }
});

app.listen(PORT, (error) => {
  if (!error) {
    console.log(`服务器已启动,监听端口 ${PORT}`);
  } else {
    console.error('服务器启动失败:', error);
  }
});

关键修改说明

  • app.all('*'):覆盖所有HTTP请求方法,确保POST/PUT等操作能转发到原应用。
  • 动态拼接targetUrl:保留用户请求的路径,让原应用返回对应页面。
  • 传递请求信息:复制原请求的headers、方法和body,保证原应用能正确处理请求。
  • 传递响应信息:将原应用的响应头、状态码完整返回,确保页面样式、脚本等资源正常加载。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 03:15:49