如何从反应客户端向运行在 Heroku 平台上的表达服务器发出 API 请求

Posted

技术标签:

【中文标题】如何从反应客户端向运行在 Heroku 平台上的表达服务器发出 API 请求【英文标题】:How to make API request from react client to express server running on the Heroku platform 【发布时间】:2019-12-26 01:20:24 【问题描述】:

我一直在尝试使用 react、redux、node 媒体服务器和 json 服务器模块将类似 Twitch 的应用程序部署到 Heroku。但是,在生产期间尝试通过 api 请求连接我的 react 客户端和 express 服务器时,我一直遇到问题。

我试图通过我的动作创建者并使用带有http://localhost:4000 基本 URL 的 axios 来发出实际请求,但这仅适用于我的本地计算机。

 const response = await streams.get("/streams");

 dispatch( type: FETCH_STREAMS, payload: response.data );
; 

你可以在https://github.com/XorinNebulas/Streamy查看我的完整回购

您还可以在 Heroku 上查看我当前部署的站点版本: https://streamy-app.herokuapp.com/

这是我的 api/server.js 文件。我的 express 服务器将在等于 process.env.PORT 的随机端口上进行监视,因此我无法知道如何在生产期间通过我的动作创建者向该随机端口发出网络请求。

const path = require("path");
const cors = require("cors");
const jsonServer = require("json-server");
const server = jsonServer.create();
const router = jsonServer.router("db.json");
const middlewares = jsonServer.defaults(
  static: "../client/build"
);
const PORT = process.env.PORT || 4000;

// Set default middlewares (logger, static, cors and no-cache)
server.use(cors());
server.use(middlewares);

if (process.env.NODE_ENV === "production") 
  // Add custom routes before JSON Server router
  server.get("*", (req, res) => 
    res.sendFile(
      path.resolve(__dirname, "../", "client", "build", "index.html")
    );
  );


// Use default router
server.use(router);
server.listen(PORT, () => 
  console.log(`JSON Server is listening on port $PORT`);
);

我希望请求能够通过并从 api/db.json 加载一些数据,resquest url 为 https://streamy-app.herokuapp.com/streams,但我得到的请求 url 为 http://localhost:4000/streams,这当然会导致 CORS 问题下面

跨域请求被阻止:同源策略不允许读取位于http://localhost:4000/streams 的远程资源。 (原因:CORS 请求未成功)。

我真的很感激任何建议,我已经为此工作了几天。

【问题讨论】:

使用 Heroku 的实例并在我的 Ubuntu 上运行您的 API,http://localhost:4000/ - 我无法重现该问题。你能分享你得到的响应的Access-Control-* 标题吗? 在开发模式下本地运行应用程序时。我可以使用响应标头获得 304 状态,包括 Access-Control-Allow-Credentials: true, Access-Control-Allow-Origin: http://localhost:3000, and Cache-Control: no-cache. 但是我知道,No response data available for this request,在生产模式下部署在 Heroku 上时。我也没有收到任何响应标头。希望这会有所帮助。 您正在使用两个域:从 Heroku 提供服务的客户端正在 http://localhost:4000/ 上请求 API。您的本地计算机上的此端口上是否有任何运行? 是的,我可以轻松地在本地运行我的 express 服务器并且一切正常,但是访问该应用程序的用户无法访问我的 json.db 数据,因为他们不在我的本地主机上。我想向部署到 Heroku 并监听端口 process.env.PORT 的 express 服务器实例发出请求。 【参考方案1】:

首先,您应该知道 Heroku不允许 公开多个端口,这意味着您应该将多个端口的方法更改为其他方式(请参阅this answer)。

其次,文件client/src/apis/streams.js 被硬编码配置为向http://localhost:4000/ 发送请求 - 这不是一个好主意。 无论您选择哪种方法 - 甚至部署到另一个主机服务器 - 您都需要根据环境动态配置 API 端点。

我还建议您:

    更改部署 react 的方式,如 here 所述。 做完以上,考虑把你的API服务和静态服务器整合一下,这样你就不需要多个端口了,然后一切就变得简单了。

【讨论】:

感谢 Avraham 提供的额外资源和所有帮助。看来我终于能够解决这个问题了。【参考方案2】:

好吧,看来我想通了。我只是进入了streams/client/package.json并添加了

"proxy":"http://localhost:4000" 

然后我进入 streams\client\src 并删除了包含我的自定义 axios 和基本 url 的 api 文件夹。为我的动作创建者使用开箱即用的 axios

const response = await axios.get("/streams");

 dispatch( type: FETCH_STREAMS, payload: response.data );
; 

现在在本地以开发模式运行时,我可以向http://localhost:4000/streams 发出请求,但在将我的节点应用程序部署到 Heroku 后,我成功向https://streamy-app.herokuapp.com/streams 发出请求 希望这可以帮助有更棘手问题的人。

【讨论】:

以上是关于如何从反应客户端向运行在 Heroku 平台上的表达服务器发出 API 请求的主要内容,如果未能解决你的问题,请参考以下文章

从 Heroku 上的子目录运行 npm

Route 使 heroku-app 崩溃,但在 localhost 上工作

从 django 静态文件提供服务并上传到 heroku 时无法找到反应静态文件

如何将 React s-s-r 应用程序部署到 Heroku?

为啥 heroku 不能在我的反应应用程序中使用代理?

使用 Mongo Cloud 从部署在 Heroku 上的 Strapi 获取数据到 ReactJs