Proxy error: Could not proxy request /getThing from myapp.herokuapp.com to http://localhost:3001

Proxy error: Could not proxy request /getThing from myapp.herokuapp.com to http://localhost:3001

我有一个使用 Facebook Create-React-App template and Nodejs/Express. I am using Heroku's Nodejs Buildpack. I was able to deploy my app to Heroku after "Dangerously Disabling Host Check" 构建的 MERN 堆栈应用程序。

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());

文件结构:

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

所以你这里没有什么问题。

Heroku runs one web dyno for you automatically, but other process types don’t start by default. To launch a worker, you need to scale it up to one 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 服务器进程的端口。并且还在同一个 dyno 中启动服务器,因此可以通过同一个 localhost 网络
  • 访问它

部署应用程序,现在可以使用了

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

https://soproxyapp.herokuapp.com/