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

Angular SSR转换后API请求代理失效问题求助

解决Angular SSR代理API请求失败返回HTML的问题

问题根源

你的API请求没被代理转发到Go服务,反而被Angular SSR的通配路由接管,返回了当前页面的HTML,触发NG04002路由匹配错误。核心问题是代理配置顺序不对,或者匹配规则未正确设置。

具体修复步骤

1. 调整代理配置位置

在server.ts中,代理规则必须放在Angular的通配路由(app.get('*', ...))之前——因为Angular的通配路由会捕获所有未被匹配的请求,代理写在后面根本无法执行。

正确的server.ts结构示例:

import { APP_BASE_HREF } from '@angular/common';
import { CommonEngine } from '@angular/ssr';
import express from 'express';
import { fileURLToPath } from 'node:url';
import { dirname, join, resolve } from 'node:path';
import { createProxyMiddleware } from 'http-proxy-middleware';

const app = express();

// 先配置API代理,必须在Angular路由之前
app.use('/api', createProxyMiddleware({
  target: 'http://localhost:8081',
  changeOrigin: true,
  pathRewrite: { '^/api': '/api' }, // 保证路径正确转发到Go服务的/api前缀
}));

const serverDistFolder = dirname(fileURLToPath(import.meta.url));
const browserDistFolder = resolve(serverDistFolder, '../browser');
const indexHtml = join(serverDistFolder, 'index.server.html');

const commonEngine = new CommonEngine();

// 再配置Angular SSR的路由处理
app.get('*', (req, res, next) => {
  const { protocol, originalUrl, baseUrl, headers } = req;

  commonEngine
    .render({
      bootstrap: () => import('./src/main.server'),
      documentFilePath: indexHtml,
      url: `${protocol}://${headers.host}${originalUrl}`,
      publicPath: browserDistFolder,
      providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
    })
    .then((html) => res.send(html))
    .catch((err) => next(err));
});

const port = process.env['PORT'] || 4000;
app.listen(port, () => {
  console.log(`Angular SSR running on http://localhost:${port}`);
});

2. 调试代理匹配情况

给代理加上日志,确认请求是否被正确捕获:

app.use('/api', createProxyMiddleware({
  target: 'http://localhost:8081',
  changeOrigin: true,
  logLevel: 'debug', // 开启调试日志
}));

启动服务后查看控制台,若出现proxying request相关日志,说明代理正常工作;若无日志,就是路径匹配存在问题。

3. 检查组件的API请求路径

确保组件里的请求使用相对路径/api/xxx:

// 推荐写法
this.http.get('/api/posts').subscribe(data => ...);

// 兼容写法(代理配置正确时也可工作)
this.http.get('http://localhost:4000/api/posts').subscribe(data => ...);

4. 确认Go服务状态和CORS配置

  • 先用Postman直接请求http://localhost:8081/api/xxx,确认能返回正确JSON,排除Go服务本身的问题。
  • 若浏览器控制台报CORS错误,需在Gin服务中添加CORS中间件,允许来自http://localhost:4000的请求:
import "github.com/gin-contrib/cors"

func main() {
  r := gin.Default()
  // 配置CORS
  r.Use(cors.New(cors.Config{
    AllowOrigins: []string{"http://localhost:4000"},
    AllowMethods: []string{"GET", "POST", "PUT", "DELETE"},
    AllowHeaders: []string{"Origin", "Content-Type"},
  }))
  // 你的API路由
  r.GET("/api/posts", func(c *gin.Context) {
    c.JSON(200, gin.H{"data": "posts list"})
  })
  r.Run(":8081")
}

验证修复

启动Angular SSR服务后,直接访问http://localhost:4000/api/xxx,若返回JSON则说明代理生效;再检查组件中的API调用,应能拿到预期的JSON数据,而非HTML。

内容的提问来源于stack exchange,提问作者k-lombard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:20:10