React 代理错误:无法将请求 /api/ 从 localhost:3000 代理到 http://localhost:8000 (ECONNREFUSED)

Posted

技术标签:

【中文标题】React 代理错误:无法将请求 /api/ 从 localhost:3000 代理到 http://localhost:8000 (ECONNREFUSED)【英文标题】:React Proxy error: Could not proxy request /api/ from localhost:3000 to http://localhost:8000 (ECONNREFUSED) 【发布时间】:2018-10-10 23:31:09 【问题描述】:

我有一个使用 jwt 向 Django 后端进行身份验证的 React 前端。后端工作正常,使用 django 视图连接得很好,但是当我尝试代理来自 React 的请求时,它给了我一个 Connection Refused 错误。

代理错误:无法将请求 /api/auth/token/obtain/ 从 localhost:3000 代理到 http://localhost:8000 (ECONNREFUSED)。

连接到http://localhost:8000/api/auth/token/obtain/ 工作正常。而且用axios发送POST请求也能正常工作,返回token json。但是当我用节点代理它时,它不起作用。

在我的package.json 我有:

  "proxy": 
    "/api/*":  
      "target": "http://localhost:8000"
    
  ,

编辑:Public repo。如果您安装了 docker,您可以轻松运行。 (使用 1 个图像和 2 个容器)。克隆后只需运行docker-compose build,然后运行docker-compose up

Edit2:请求标头:

*General*
Request URL: http://localhost:3000/api/auth/token/obtain/
Request Method: POST
Status Code: 500 Internal Server Error
Remote Address: [::1]:3000
Referrer Policy: no-referrer-when-downgrade

*Response Headers*
HTTP/1.1 500 Internal Server Error
X-Powered-By: Express
Date: Mon, 30 Apr 2018 21:23:17 GMT
Connection: keep-alive
Transfer-Encoding: chunked

*Request Headers
POST /api/auth/token/obtain/ HTTP/1.1
Host: localhost:3000
Connection: keep-alive
Content-Length: 45
Pragma: no-cache
Cache-Control: no-cache
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/65.0.3325.181 Safari/537.36
Content-Type: application/json
Accept: */*
Referer: http://localhost:3000/login
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,fr;q=0.8,ja;q=0.7

【问题讨论】:

如果您发布您的 Django 和 Node 代码会很有帮助。 @MattMorgan 对不起。已添加。 不确定,无法快速在本地运行。 CRA 文档表明您的 target 模式可能是错误的。您是否尝试过:"/api" 而不是 "/api/*"...想知道它是否在尝试匹配 api/only-one-more-element @MattMorgan 不适用于 /api/api//api/*,或仅适用于 "proxy":"http://localhost:8000" 【参考方案1】:

所以问题是因为 Node 开发环境和 Django 开发环境都在单独的 docker 容器中运行,所以 localhost 指的是节点容器,而不是桥接网络。

所以关键是使用容器链接,这些链接是在使用docker-compose 时自动创建的,并将其用作主机名。所以我把它改成了

"proxy": 
    "/api":  
        "target": "http://django:8000"
    
,

只要您使用相同的docker-compose 命令启动两个容器,这就会奏效,否则您必须在docker-compose.yml 文件中手动指定 external_links。

【讨论】:

我遇到了同样的问题,对我来说,当 package.json 中的代理是一个对象时出现错误,所以它必须是一个字符串,但 http://<container-name>:<port> 工作得很好!非常感谢【参考方案2】:

我也遇到了同样的问题。大多数搜索结果都提到将"secure": false"ignorePath": true 添加到您的代理配置中。像这样的:

"proxy": 
    "/api/*":  
      "target": "http://localhost:8000",
      "secure": false
    
  ,

可能值得一试,但不幸的是,这些都不适合我。虽然每个地址(http://localhost:3000 和 http://localhost:8000)在浏览器中都可以正常工作,但可能因为容器实际上是代理它需要使用 Docker 地址?

编辑--

好吧,我想我明白了。我相信它确实与容器到容器的通信有关。查看您的docker-compose,您的api 服务器称为django。将您的 package.json 文件更改为:

"proxy": 
    "/api/*":  
      "target": "http://django:8000",
      "secure": false
    
  

【讨论】:

我昨天确实修复了这个问题,并发布了我如何修复它的答案。对我来说,这是因为两台服务器运行在不同的节点容器上,所以localhost 并没有指代与 django 相同的主机。 这个答案极大地帮助我解决了今天的问题,非常感谢@VincentJr【参考方案3】:

我遇到了类似的问题,但在 Mac 机器上。我在 package.json 中将localhost 更改为127.0.0.1,这对我有用,如下所示:

"proxy": "http://127.0.0.1:5000"

【讨论】:

试过了,还是不行。 React 仍在尝试向 localhost:3000 发送请求【参考方案4】:

如果您使用的是较新版本的 CRA 2.0+,则需要通过手动代理执行此操作。 https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development#configuring-the-proxy-manually

【讨论】:

【参考方案5】:

如果您不想设置 docker compose,也可以使用 docker 网络

创建网络并在该网络中运行 docker 容器

docker network create webapp_network

docker run -d -p 5000:5000 --name webapp_backend --network webapp_network webapp_backend_image

docker run -d -p 3000:3000 --name webapp_frontend --network webapp_network webapp_frontend_image

在我的前端 React webapp 的 package.json 中添加了一行:

"proxy": "http://webapp_backend:5000"

请注意,您现在可以使用容器名称而不是 localhost 来引用您的后端

【讨论】:

【参考方案6】:

昨天将Docker升级到版本v19.03.13(在Mac上)后可以看到错误,重新启动Docker解决了这个问题。该应用程序还运行Node.js/React,但不是Django。基本上,我在连接到MongoDB Atlas 时遇到了与身份验证/从云数据库中获取任何内容相关的问题。

【讨论】:

【参考方案7】:

正确答案是使用手动代理和

    目标=码头地址django:4000 正确的主机头localhost:8000

因为如果 Django 使用返回绝对 url 的reverse 函数

reverse('preview-mail', args=[mail.pk],request=request)

您需要为其设置正确的 HOST 标头,否则您可能会得到类似的结果 URL https://django:4000/your-url`

const proxy = require('http-proxy-middleware');

module.exports = function(app) 
  app.use(
    proxy('/api', 
      target: 'http://django:4000',
      changeOrigin: true,
      secure: false,
      pathRewrite: 
        '^/api': ''
      ,
      onProxyReq: function (proxyReq, req, res) 
          proxyReq.setHeader("host", 'localhost:8000')
      
    )
  )


【讨论】:

【参考方案8】:

为 localhost 选择 exact 值来填充“目标”属性主要是解决方案(它可以是 localhost, 127.0.0.1, [::1] )。

mac 用户应该输入终端来获取解决方案:

sudo lsof -iTCP -sTCP:LISTEN -n -P

【讨论】:

【参考方案9】:

如果您正在开发 MERN 堆栈应用程序,请确保您不在客户端文件夹中。你需要在根目录下。在根目录下,在终端中运行此命令。 npm run start:dev

【讨论】:

太棒了。谢谢你。我忘了我在我的应用程序的客户端文件夹中......?

以上是关于React 代理错误:无法将请求 /api/ 从 localhost:3000 代理到 http://localhost:8000 (ECONNREFUSED)的主要内容,如果未能解决你的问题,请参考以下文章

无法将来自 localhost:3000 的请求代理到 localhost:7000 ReactJs

对 php 后端的 create-react-app 代理请求

使用 React Router 的代理 API 请求

react中如何使用反向代理

react配置API请求代理

无法访问从 React 客户端到 Rails api 的 POST 请求中发送的参数