【问题标题】:Proxy error: Could not proxy request /getThing from myapp.herokuapp.com to http://localhost:3001代理错误:无法将请求 /getThing 从 myapp.herokuapp.com 代理到 http://localhost:3001
【发布时间】:2018-08-19 09:11:09
【问题描述】:

我有一个使用 Facebook 的 Create-React-App 模板和 Nodejs/Express 构建的 MERN 堆栈应用程序。我正在使用Heroku's Nodejs Buildpack。在"Dangerously Disabling Host Check" 之后,我能够将我的应用部署到 Heroku。

Reproducible Demo(自述文件中的说明)

我的网站显示信息,但对我的后端的请求不起作用(服务器和 React 在同一个 Heroku 应用程序上运行)。当我的站点尝试向 /getThing 等端点发出请求时,浏览器控制台会显示:

XML Parsing Error: syntax error
Location: https://myapp.herokuapp.com/getThing
Line Number 1, Column 1:
getThing:1:1
Error: Request failed with status code 500

我的Heroku logs 给了我这个(仅包括相关部分):

2018-03-11T04:27:01.058036+00:00 heroku[router]: at=info method=POST path="/getThing" host=myapp.herokuapp.com request_id=e587a6ee-1dbf-4a2d-9caf-07d9478b5a39 fwd="128.84.126.1
26" dyno=web.1 connect=1ms service=32ms status=500 bytes=297 protocol=https
2018-03-11T04:27:01.032269+00:00 heroku[router]: at=info method=GET path="/static/js/bundle.js.map" host=myapp.herokuapp.com request_id=a4fd078d-07f1-4796-b0fe-555f8f389920 fwd="128.84.126.126"
 dyno=web.1 connect=0ms service=7ms status=304 bytes=176 protocol=https
2018-03-11T04:27:01.055673+00:00 app[web.1]: Proxy error: Could not proxy request /getThing from myapp.herokuapp.com to http://localhost:3001/.
2018-03-11T04:27:01.055735+00:00 app[web.1]: See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (ECONNREFUSED).
2018-03-11T04:27:01.055787+00:00 app[web.1]:
2018-03-11T04:27:02.212247+00:00 heroku[router]: at=info method=GET path="/sockjs-node/info?t=1520742420523" host=myapp.herokuapp.com request_id=91c5363e-dbf3-4d15-9482-b44bc1dc3205 fwd="128.84
.126.126" dyno=web.1 connect=0ms service=3ms status=200 bytes=363 protocol=https

第 4 行是错误所在。我的 package.json 中一直是 using a proxy,但我读过 Heroku 忽略了这一点,所以这应该不是问题。我的 package.json 包含在下面。

{
  "name": "myapp",
  "version": "0.1.0",
  "private": true,
  "proxy": "http://localhost:3001/",
  "dependencies": {
    "@sendgrid/mail": "^6.2.1",
    "async": "^2.6.0",
    "aws-sdk": "^2.205.0",
    "axios": "^0.14.0",
    "body-parser": "~1.17.1",
    "cookie-parser": "~1.4.3",
    "cors": "^2.8.4",
    "debug": "^2.6.9",
    "dotenv": "^5.0.1",
    "express": "~4.15.2",
    "express-fileupload": "^0.4.0",
    "font-awesome": "^4.7.0",
    "foreman": "^2.0.0",
    "history": "^4.7.2",
    "marked": "^0.3.17",
    "milligram": "^1.3.0",
    "milligram-react": "0.0.0",
    "mongodb": "^2.2.35",
    "mongoose": "^4.13.11",
    "morgan": "~1.8.1",
    "nodemailer": "^4.6.0",
    "nodemon": "^1.17.1",
    "react": "^16.2.0",
    "react-bootstrap": "^0.32.1",
    "react-dom": "^16.2.0",
    "react-fontawesome": "^1.6.1",
    "react-icons": "^2.2.7",
    "react-onclickoutside": "^6.7.1",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-scripts": "1.0.17",
    "react-table": "^6.8.0",
    "sendgrid-web": "0.0.5",
    "serve-favicon": "~2.4.2",
    "supports-color": "^5.3.0"
  },
  "engines": { "node": "6.11.3", "npm": "5.7.1"},
  "scripts": {
    "start": "react-scripts start | node server.js",
    "start-dev": "set DEBUG=* & nodemon server.js",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}

这是启动服务器的服务器代码:

const port = process.env.PORT || 3001;
app.listen(port, function () {
    debug(`api running on port ${port}`);
});

我什至允许cors无处不在:

const cors = require('cors');
app.use(cors());

文件结构:

任何想法将不胜感激。如果您需要任何其他信息,请告诉我。

【问题讨论】:

  • 我部署了您的应用并重现了该问题。所以你在这里有多个问题。代理实际上用于将请求发送到3001,但在您的server.js 中,您使用const port = process.env.PORT || 3001;,这意味着您不使用3001。您使用 heroku 提供的随机端口。此外,您不应该使用Procfile,这将启动两个测功机。您可以同时启动它们。这篇文章解释了应该怎么做originmaster.com/…。明天会发布一个详细的答案,这将帮助您解决问题

标签: node.js reactjs express heroku create-react-app


【解决方案1】:

所以你这里有几个问题。

Heroku 会自动为您运行一个 web dyno,但默认情况下不会启动其他进程类型。要启动一个工作器,您需要将其扩展到一个测功机:

这意味着默认情况下您的 API dyno 甚至没有启动。您需要执行以下命令才能启动它

heroku ps:scale api=1

但它也无济于事,因为您的 API 无法到达 http 并且 web dyno 无法知道 api 在哪里。有可能做到这一点,但我不会为这个答案进入那个解决方案

您可以在下面找到更多详细信息

https://devcenter.heroku.com/articles/dyno-dns-service-discovery

您可能需要更改您的server.js,如下所示

const host = process.env.HEROKU_PRIVATE_IP || '0.0.0.0';
//starts the server and listens for requests
app.listen(port, host, function () {
    debug(`api running on port ${port}`);
});

并且还将package.json更新为

"proxy": "http://<apidnsname>:3001"

但正如我所说,我不喜欢这种解决方案,因为它需要在 package.json 中硬编码 dnsname

实际修复

  • 删除 Procfile(heroku 将自动运行 npm start
  • 添加并发包npm add concurrently
  • start 脚本更改为"start": "concurrently \"react-scripts start\" \"PORT=3001 node server.js\""。这有两件事。修复您的 api 服务器进程的端口。并且还在同一个测功机中启动服务器,因此可以通过同一个 localhost 网络访问它

部署应用程序,现在它可以工作了

下面是一个示例工作应用程序供您检查,它会上线一段时间,然后我会删除它

https://soproxyapp.herokuapp.com/

【讨论】:

  • 这在heroku上完美运行!虽然对我来说不是问题,但使用这种方法在本地主机上本地运行时我会收到相同的错误。出于好奇,你知道这是为什么吗?
  • 我也在本地测试和工作。你应该使用npm start
  • 这样一个简单的应用程序加载这么长时间是否有原因?我不认为 Heroku 免费计划有问题,因为并非所有 Heroku 免费网站都这么慢。做这些在线速度测试会给你一个很低的数字,但实际上尝试加载网站在第一次或两次加载时非常慢。关于如何改变这种情况的任何想法?
  • 似乎 websocket 握手需要相当长的时间。在我的身上花了将近1.6min
  • 有趣...您知道解决此问题的任何方法吗?如果没有,我可以提出另一个问题。
猜你喜欢
  • 1970-01-01
  • 2023-02-02
  • 2020-01-31
  • 2018-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-09-26
  • 2020-06-20
  • 2019-07-07
相关资源
最近更新 更多