当使用Angular应用程序进行代理时出现504(网关超时)错误

16

我正在尝试设置 Angular 应用程序以与 2 个不同的本地主机配合使用。

我已在项目根目录下创建了一个名为 backend 的文件夹,并在其中添加了一个名为 echo.php 的文件。在项目根目录中,我还创建了一个名为 proxy.conf.json 的文件,并将以下内容添加到其中:

{
  "/backend/**": {
    "target": "http://localhost:80",
    "secure": false

  }
}

我尝试使用以下代码获取echo.php:

  ngOnInit(){
    this.http.get('http://localhost:4200/backend/echo.php').subscribe(data => {
      console.log(data);      
    });
  }

启动Angular应用:

ng serve --port 4200 --host 0.0.0.0 --proxy-config proxy.conf.json

在浏览器控制台中,我遇到了一个 504错误 网关超时。而在终端中,这个错误听起来有点不同:

[HPM] Error occurred while trying to proxy request /backend/echo.php from localhost:4200 to http://localhost:80 (ENOTFOUND)
我不知道自己错在哪里,请问你能指引我正确的方向吗?我可以通过这个 URL http://localhost/backend/echo.php 直接访问非 Angular(运行于 80 端口)服务器上的文件。

编辑:

echo.php:

<?php
echo "data from php";

如果您在直接使用后端时遇到错误,那么这个错误似乎与Angular无关。相比Angular代码,将问题标记为 php 并包含您的PHP代码和相关配置,可能会更有帮助。(您是否使用了某个PHP框架?也请包含该信息) - Daniel
当我直接使用http://localhost/backend/echo.php访问资源时,没有出现任何错误。只有在从localhost:4200代理到localhost:80时才会抛出错误。 - sanjihan
我刚刚尝试了你的代码,在我的机器上可以运行。当你说“在终端中,错误听起来有点不同”时,你是在终端中使用curl调用服务器还是指ng serve记录的消息?如果是curl,请发布你使用的命令。此外,你在哪个系统/容器上运行这个程序? - Daniel
1
当使用ng serve时,会出现错误消息。我不确定您所说的系统/容器是什么意思。我在OSX上运行它:) 与此同时,我意识到添加“changeOrigin”:true可以解决这个问题(不确定为什么文档中没有提到)。但是猜猜,问题并没有停止:D https://stackoverflow.com/questions/47613765/php-script-not-getting-executed-when-run-with-proxy-server-in-angular 。难道配置Angular真的应该如此痛苦吗? - sanjihan
1
好的,问题终于被解决了。这次是彻底的 :D changeOrigin并没有真正解决它。我改变了GET链接,实际上在不知情的情况下提供静态PHP文件。在更改资源链接后,代理甚至从未被使用过。真正的问题在于在proxy.conf.json中指定目标。我在下面发布了答案。 - sanjihan
显示剩余2条评论
6个回答

24

经过很多很多小时的努力,我找到了真正的问题所在。它源于在 proxy.conf.json 中指定目标。下面是正确的方式:

After many, many hours I found the real issue. It stems from specifying target in proxy.conf.json. This is correct:


{
  "/backend/*": {
    "target": "http://127.0.0.1",
    "secure": false,
    "changeOrigin":true,
    "logLevel": "debug"
  }
}

而这则不是:

{
  "/backend/*": {
    "target": "http://localhost",
    "secure": false,
    "changeOrigin":true,
    "logLevel": "debug"
  }
}

这可能与无法独立执行ng serve有关。

ng serve 

命令返回错误:

getaddrinfo ENOTFOUND localhost
Error: getaddrinfo ENOTFOUND localhost
    at errnoException (dns.js:28:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)

这是一个老问题,我从未找到这个错误的根本原因。 相反,我只是使用了ng serve --port 4200 --host 0.0.0.0来解决它。

如果有人能解释一下为什么这样可以解决问题,那就太棒了。 我的/etc/hosts文件内容如下:

127.0.0.1       localhost
255.255.255.255 broadcasthost
::1             localhost
192.168.1.1      router.hm
127.0.0.1 My-MBP # added by Apache Friends XAMPP

1
经过4个小时的尝试解决完全相同的问题,我发现在OSX上运行ng serve --port 4200 --host 0.0.0.0才能使其正常工作!惊讶的是关于这个问题并没有更多的信息! - David
我发现我的proxy.conf.json文件中有一个拼写错误。感谢您引导我找到解决方案。 - Orin
在尝试为Python服务器代理API调用时,我遇到了类似的问题。使用127.0.0.1而不是localhost解决了这个问题。谢谢并点赞! - Malik
使用http://127.0.0.1代替http://localhost对我有所帮助,谢谢。 - undefined

3

代理配置文件

{
    "/api/*":{
    "target" : "http://127.0.0.1:1234",
    "changeOrigin" : true,
    "secure" : false
    }
}

修改 proxy.conf.json 文件,并将 PHP 开发服务器设置为 127.0.0.1:1234 而非 localhost:1234,这样可以解决我的问题。

2
我看到了这个错误:在Angular应用程序中代理时出现504(网关超时)错误。你可能会对这个答案感到惊讶,我发现我犯了一个非常愚蠢的错误,忽视了代理目标。这个错误是在proxy.json文件中一个简单的拼写错误。目标设置为:locahost而不是localhost。尽管听起来很傻,但我花了一个多小时才发现问题,我的眼睛肯定需要检查一下了。

目前您的回答不太清楚。请编辑并添加更多细节,以帮助其他人了解这个答案如何解决所问的问题。您可以在 帮助中心 找到有关如何编写好答案的更多信息。 - Community
当然可以。我增加了更多的上下文。 - Ravindran Keshavan

1

我不知道为什么,但在proxy.conf.json中的url顺序非常重要。

例如,如果您将您的url '/api/person/getPerson'放在/api之后,那么我会得到与OP相同的错误:

    '/api': {
        target: 'http://localhost:800/',
        secure: false,
        logLevel: "debug",
        changeOrigin: true,
        agent: agent,
        onProxyRes: onProxyRes
    },
    '/api/person/getPerson': {
        target: 'http://localhost:88888/',
        secure: false,
        logLevel: "debug",
        changeOrigin: true,
        pathRewrite: {
          "^/api/person/getPerson": ""
        },
        onProxyRes(proxyRes, req, res) {
          res.json(
            [
              {
                "id": "id",
                "name": "Jon Skeet"
              },
            ]
            );
            return res;
        }
    }

然而,如果将此URL '/api/person/getPerson' 放在 '/api' 之前,则可以正常工作:

    '/api/person/getPerson': {
            target: 'http://localhost:88888/',
            secure: false,
            logLevel: "debug",
            changeOrigin: true,
            pathRewrite: {
              "^/api/person/getPerson": ""
            },
            onProxyRes(proxyRes, req, res) {
              res.json(
                [
                  {
                    "id": "id",
                    "name": "Jon Skeet"
                  },
                ]
          );
          return res;
        }
    },
    '/api': {
        target: 'http://localhost:800/',
        secure: false,
        logLevel: "debug",
        changeOrigin: true,
        agent: agent,
        onProxyRes: onProxyRes
    },

0

我尚未尝试使用ng serve进行代理,但对于我来说,有效的方法是将后端应用程序放在根目录中,将Angular部分放在名为viewfront-end或您喜欢的其他文件夹名称下的子目录中。请查看Launch angular 4 from Hapi js获取一个类似的问题,只不过是涉及到Node.js。如果您有任何疑问,请随时要求更多详细信息。


-3

我已经使用了超时和重试来解决这个504错误,例如retryWhen(error => error.delay(5000)).timeout(900000)。


1
欢迎来到Stackoverflow。请详细说明这将如何帮助解决问题。如果您要发布一些代码,请使用代码块。 - Sachin Gupta
对于一个 HTTP 请求,如果我们得到了 504 网关超时错误,而不是立即抛出异常,我们可以使用 retryWhen 在一定延迟后重新获取响应。 - Atanu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接