【问题标题】:Axios POST to Heroku is blocked by CORS - Network Error: 503Axios POST 到 Heroku 被 CORS 阻止 - 网络错误:503
【发布时间】:2022-01-11 07:55:45
【问题描述】:

我正在使用 MERN Stack,一切正常,直到我对 UI 进行了一些更改(将代码移动到不同的组件、更改样式......)。

  • 我没有更改Axios请求中的任何代码,只有这个POST请求不起作用,其他请求正常。

  • 我已经在我的后端设置了 CORS

  • 我可以访问my-project.herokuapp.com/insert 链接,Heroku 日志中没有错误。客户端或服务器端没有抛出错误。

  • 当我点击表单中的添加到列表按钮时,包含Axios POST请求的addToList函数不会将数据发送到数据库像以前一样。

  • 30 秒后 - 出现此错误:

请帮助我了解发生了什么以及如何解决此问题。我一直在寻找其他解决方案,但我不知道如何应用于我的案例。 谢谢! :)



这是我的代码:

客户端的addToList函数:

const [foodName, setFoodName] = useState('')
const [isVegetarian, setIsVegetarian] = useState('')
const [priceRange, setPriceRange] = useState('$')
const [foodUrl, setFoodUrl] = useState('')
const [foodList, setFoodList] = useState([])

const addToList = async (event) => {
      event.preventDefault()
      try {
        await Axios.post(
        "https://my-project.herokuapp.com/insert", 
        {
          foodName: foodName,
          isVegetarian: isVegetarian,
          priceRange: priceRange,
          foodUrl: foodUrl,
        }
        )
        .then(() => {
          setFoodName('')
          setIsVegetarian('')
          setPriceRange('$')
          setFoodUrl('')
        })
      } catch(err) {
        console.error(`The error is ${err}`)
      }
    }

Dinner.js - Mongoose 架构

const mongoose = require('mongoose')

const DinnerSchema = new mongoose.Schema({
    foodName: {
        type: String,
        required: true,
    },
    isVegetarian: {
        type: String,
        required: true,
    },
    priceRange: {
        type: String,
        required: true,
    },
    foodUrl: {
        type: String,
        required: true,
    }
})

const Dinner = mongoose.model("dinners", DinnerSchema)
module.exports = Dinner

服务器的 index.js 和不起作用的端点:

const express = require("express")
const mongoose = require("mongoose")
const cors = require('cors')
const app = express()
require("dotenv").config()

const DinnerModel = require('./models/Dinner')

app.use(express.json())
app.use(cors())

// Connect to MongoDB
mongoose.connect(
    'mongodb+srv://linktoDB', 
    {
        useNewUrlParser: true,
    }
)

// Create:
app.post("/insert", async (req, res) => {
    const foodName = req.body.foodName
    const isVegetarian = req.body.isVegetarian
    const priceRange = req.body.priceRange
    const foodUrl = req.body.foodUrl

    const dinner = new DinnerModel(
        { 
            foodName: foodName, 
            isVegetarian: isVegetarian,
            priceRange: priceRange,
            foodUrl: foodUrl
        }
    )

    try {
        await dinner.save()
        res.send("Inserted successfully")
        
    } catch(err) {
        console.log(err)
    }
})

// Creating a port:
app.listen(process.env.PORT || 3001, () => {
    console.log("Server is connected.")
})

我后端的 package.json

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "engines": {
    "node": "12.20.1"
  },
  "scripts": {
    "start": "node index.js",
    "devStart": "nodemon index.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "cors": "^2.8.5",
    "dotenv": "^10.0.0",
    "express": "^4.17.2",
    "mongoose": "^6.1.3",
    "nodemon": "^2.0.15",
    "validator": "^13.7.0"
  }
}

更新 1

我添加了这段代码,但它仍然不起作用:

const corsOptions = {
 "origin": "*",
 "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
 "preflightContinue": false,
 "optionsSuccessStatus": 204,
}

 app.use(cors(corsOptions))

这是我尝试添加文档时的预检请求和响应。一种状态为 204,一种状态为 503: https://i.stack.imgur.com/v1IcS.png https://i.stack.imgur.com/AzH8d.png

更新 2

当我检查有效载荷时,我发现了问题所在。请在下面查看我的答案。 感谢大家帮助我解决这个问题!

【问题讨论】:

  • 这听起来很傻。您是否保存了后端文件并重新启动了服务器??
  • 您是否看到后端抛出任何错误?
  • @ikhvjs 是的,我做到了。我什至再次提交客户端和服务器文件夹只是为了确保。但是错误仍然存​​在:/
  • @TheWhiteFang 只是我在addToList 函数中发现的控制台错误。后端的终端什么也没说。
  • 在本地 (localhost) 运行应用程序时会出现此错误。要在本地运行您的应用程序而不会出现此错误,请使用将 CORS 标头添加到代理请求的代理,例如 CORS Anywhere

标签: javascript reactjs express axios cors


【解决方案1】:

问题

根据Axios's source code,如果Axios.post的第二个参数是一个对象,Axios将请求的内容类型设置为application/json。这个值是这样的,根据the Fetch standard,服务器必须允许Content-Type标头才能成功进行CORS预检。

但是,您依赖的是Express.js's CORS middleware's default configuration

app.use(cors())

并且该默认配置不允许任何请求标头。

解决方案

在您的 CORS 配置中允许 Content-Type 请求标头:

const corsOptions = {
  "origin": "*",
  "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
  "preflightContinue": false,
  "optionsSuccessStatus": 204,
  "allowedHeaders": ["Content-Type"]
}
app.use(cors(corsOptions))

【讨论】:

  • 我尝试添加您的解决方案而不是app.use(cors()),但将var 替换为const 并在204 之后添加了一个逗号,但仍然存在相同的错误:(
  • @JulieLai 好的。您能否编辑您的问题并在浏览器的“网络”选项卡中添加预检请求和响应的屏幕截图?
  • 感谢您的建议!我想当我点击 Payload 时我已经发现了问题所在。它收到的来自isVegetarian 的数据是一个空字符串,因为我将其状态从布尔值更改为字符串并忘记了初始状态,架构required 与它发生冲突,因此它不会将数据发送到数据库。我的最后一个问题是:如果不再是问题,我们需要允许corsOptions 还是只允许默认配置?谢谢!
  • @JulieLai 您可以尝试再次依赖默认配置,但是,如果我对您的屏幕截图的分析是正确的,您将收到 CORS 错误。您仍然需要明确允许 Content-Type 标头。
  • @JulieLai 在 CORS 选项的 allowedHeaders 属性中列出 Content-Type 标头,正如我在上面所做的那样,应该就足够了。如果你有兴趣了解更多关于 CORS 的知识,我可以推荐developer.mozilla.org/en-US/docs/Web/HTTP/CORS
【解决方案2】:

在“网络”选项卡中检查 POST 请求的有效负载时,我发现了导致 503 错误的原因。

  • 它收到了我的 isVegetarian 值的空字符串。

  • 出现空字符串是因为我将 isVegetarian schema 类型从 Boolean 更改为 String 但忘记将初始状态更改为特定值: const [isVegetarian, setIsVegetarian] = useState('')

  • Schema 中,我将 isVegetarian 设置为 required: true,因此它不会接受空字符串。

-> 所以如果你有正确的 CORS 配置并且仍然有相同的 503 错误。也许检查 Network 选项卡中的预检请求、响应和有效负载,看看是否有任何剩余代码需要查看。

【讨论】:

  • 你的后台怎么不弹出这个isVegetarian的错误?
  • @ikhvjs 我不确定,这就是为什么我花了几天时间来调试它。后端终端没有崩溃或抛出任何错误。
  • 我想我知道为什么。你应该把你的new DinnerModel() 放在try block 里面。此外,您应该在 catch block 中发送类似 res.send(err); 的错误
  • @ikhvjs 我尝试将const dinner = new DinnerModel({object: object,..}) 移动到try block 并在catch block 中发送一个错误,然后尝试再次重现该错误。后端节点终端仍然什么也没说,只有前端控制台像以前一样出现503错误。
  • 感谢您的反馈。如果你 console.log(err) 在 catch block 之前 res.send 怎么办?我认为它应该在您尝试初始化模式时跟踪错误。
猜你喜欢
  • 2021-10-17
  • 2021-12-25
  • 2020-09-29
  • 2023-01-19
  • 1970-01-01
  • 2021-10-13
  • 2019-10-01
  • 2021-02-07
  • 2019-12-25
相关资源
最近更新 更多