【问题标题】:CORS error for Post requests Node.js and ReactPost 请求 Node.js 和 React 的 CORS 错误
【发布时间】:2021-11-02 11:17:29
【问题描述】:

我对代码的 get 请求有效,但是当涉及到 post 请求时,我收到一个 cors 错误:

CORS 策略已阻止从源“client.com”访问“api.com”处的 XMLHttpRequest:请求的资源上不存在“Access-Control-Allow-Origin”标头。

我已经尝试了所有与解决此问题相关的方法,但我一直得到相同的结果。我想知道是不是因为我的套接字服务器?很郁闷。

我的节点代码:

const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const session = require("cookie-session");
const cors = require("cors");
const server = require("http").createServer(app);
const rateLimit = require("express-rate-limit");
const io = require("socket.io")(server, {
  cors: {
    origin: "*",
  },
});
const multer = require('multer');
const { v4: uuidv4 } = require('uuid');
let path = require('path');


app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use(
  session({
    resave: false,
    saveUninitialized: true,
    secret: "shhhhhh",
  })
);

app.use(function (req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept"
  );
  next();
});



app.use(cors());

const {
  registerTeacher,
  loginTeacher,
  getOneTeacher,
  getAllTeachers,
  postAvailibility,
  deleteExpired
} = require("./teachers");

const {
  loginStudent,
  registerStudent,
  getOneStudent,
  bookTeacher,
} = require("./students");

const { postMessage, getMessages } = require("./classes");

///images
const storage = multer.diskStorage({
  destination: function(req, file, cb) {
      cb(null, 'images');
  },
  filename: function(req, file, cb) {   
      cb(null, uuidv4() + '-' + Date.now() + path.extname(file.originalname));
  }
});

const fileFilter = (req, file, cb) => {
  const allowedFileTypes = ['image/jpeg', 'image/jpg', 'image/png'];
  if(allowedFileTypes.includes(file.mimetype)) {
      cb(null, true);
  } else {
      cb(null, false);
  }
}

let upload = multer({ storage, fileFilter });

////teacher routes
app.post("/api/teachers/register", upload.single('photo'), registerTeacher);
app.post("/api/teachers/login", loginTeacher);
app.get("/api/teachers/:teacherId", getOneTeacher);
app.post("/api/teachers/:teacherId/calender", postAvailibility);
app.delete("/api/teachers/:teacherId/calender", deleteExpired)

///student routes
app.post("/api/students/register", upload.single('photo'), registerStudent);
app.post("/api/students/login", loginStudent);
app.get("/api/students/:studentId", getOneStudent);
app.get("/api/students/:studentId/ourteachers", getAllTeachers);
app.post("/api/students/:studentId/ourteachers/:teacherId", bookTeacher);


///Class Routes for getting messages only
app.put("/api/:classId/:studentId/:teacherId", postMessage);
app.get("/api/:classId/:studentId/:teacherId", getMessages);

////socket
let users = [];

const addUser = (userId, socketId) => {
  !users.some((user) => user.userId === userId) &&
    users.push({ userId, socketId });
};

const removeUser = (socketId) => {
  users = users.filter((user) => user.socketId !== socketId);
};

const getUser = (userId) => {
  return users.find((user) => user.userId === userId);
};

io.on("connection", (socket) => {
  ///connected
  ///take userId and socketId
  socket.on("addUser", (userId) => {
    addUser(userId, socket.id);
    io.emit("getUsers", users);
  });

  ///send and get message
  socket.on("sendMessage", ({ senderId, receiverId, text }) => {
    const user = getUser(receiverId);
    io.to(user.socketId).emit("getMessage", {
      senderId,
      text,
    });
  });

  socket.emit("me", socket.id);

  socket.on("callUser", (data) => {
    io.to(data.userToCall).emit("callUser", {
      signal: data.signalData,
      from: data.from,
      name: data.name,
    });
  });

  socket.on("answerCall", (data) => {
    io.to(data.to).emit("callAccepted", data.signal);
  });

  ///for mouse

  socket.on("sendLines", (data) => {
    io.to(data.to).emit("getLines", data.lines);
  });

  socket.on("clearLines", (data) => {
    io.to(data.to).emit("getClearLines", data.lines);
  });

  ///for slides

  socket.on('sendSlidePosition', (data)=>{
    io.to(data.to).emit('getSlidePosition', data.slidePosition)
  })

  socket.on('sendAllow', (data)=>{
    io.to(data.to).emit('getAllow', data.data)
  })

  ///disconnected
  socket.on("disconnect", () => {
    console.log("User disconnected");
    removeUser(socket.id);
    io.emit("getUsers", users);
  });
});

let port = process.env.PORT;
if (port == null || port == "") {
  port = 5000;
}

server.listen(port, function () {
  console.log("Successful port connection");
});

我的反应代码:

import { useState } from "react";
import axios from "axios";
import { useHistory } from "react-router-dom";
import { FormControl, Input, Button } from "@material-ui/core";

function TeacherSignup() {
  let history = useHistory();

  const url =
    "myapi.com";
  const [data, setData] = useState({
    name: "",
    email: "",
    age: "",
    phoneNumber: "",
    nationality: "",
    country: "",
    city: "",
    street: "",
    postalCode: "",
    password: "",
    confirmPassword: "",
  });

  function submit(e) {
    e.preventDefault();
    if (data.password !== data.confirmPassword) {
      alert("passwords must match");
    }
    axios
      .post(url, {
        name: data.name,
        email: data.email,
        age: data.age,
        phoneNumber: data.phoneNumber,
        country: data.country,
        city: data.city,
        street: data.street,
        password: data.password,
        postalCode: data.postalCode,
        nationality: data.nationality,
      })
      .then((res) => {
        console.log(res.data._id);
        history.push(`/teachers/${res.data._id}`);
      });
  }

  function handle(e) {
    const newData = { ...data };
    newData[e.target.id] = e.target.value;
    setData(newData);
    console.log(newData);
  }

  return (
    <div className='login-form'>
      <h1>Register Teacher</h1>
      <form onSubmit={(e) => submit(e)}>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="name"
              value={data.name}
              placeholder="Name"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="email"
              value={data.email}
              placeholder="Email"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="age"
              value={data.age}
              placeholder="Age"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="phoneNumber"
              value={data.phoneNumber}
              placeholder="Phone Number"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="nationality"
              value={data.nationality}
              placeholder="Nationality"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="country"
              value={data.country}
              placeholder="Country"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="city"
              value={data.city}
              placeholder="City"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="street"
              value={data.street}
              placeholder="Street"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="postalCode"
              value={data.postalCode}
              placeholder="Postal Code"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="password"
              value={data.password}
              placeholder="Password"
              type="text"
            ></Input>
          </FormControl>
        </div>
        <div className="login-input">
          <FormControl>
            <Input
              onChange={(e) => handle(e)}
              id="confirmPassword"
              value={data.confirmPassword}
              placeholder="Confirm Password"
              type="text"
            ></Input>
          </FormControl>
        </div>

        <Button type="submit">Submit</Button>
      </form>
    </div>
  );
}

export default TeacherSignup;

【问题讨论】:

  • 为什么要在 app.use(cors()) 调用之前明确设置 CORS 响应标头?我会尝试删除它,因为它可能与 cors 冲突。
  • 我不想挑剔,但错误是提到 api.com 并且您的反应服务器正在连接到 myapi.com 这只是一个错字还是这两个不同的服务器?
  • 您可以尝试删除app.use(cors()) 并在您的自定义cors 处理程序(即res.header.set("Access-Control-Allow-Origin", "*"))中设置一个断点以查看该断点是否被命中?如果它被命中,则检查该特定请求的响应是否包含 ACAO 标头。如果不是(如错误所示),还有其他东西会干扰您的响应并可能重置标题...
  • 如果断点未命中,则说明您的服务器设置存在其他问题,无法执行所有中间件。然后你应该尝试将你的服务器减少到一个最小的例子。例如尝试删除socket.io 和其他中间件并检查问题是否仍然存在......如果你有工作配置,添加回各个部分,看看问题是否再次出现......
  • 你能不能也检查一下浏览器,如果有预检(OPTIONS)请求被发送,如果是,这个请求的结果是什么...

标签: javascript node.js reactjs sockets


【解决方案1】:

我将删除在 app.use(cors()) 之前设置的显式 CORS 标头,并将 methods: ['GET', 'POST', 'DELETE', 'OPTIONS'] 添加到您的 io 配置中。

从 Socket.IO v3 开始,您需要显式启用跨域资源共享 (CORS)。

【讨论】:

  • 我试过了,还是不行。同样的错误
  • 很难说没有关于确切错误消息的更多信息。确保支持预检请求:app.options('*', cors()).
  • 您可能还试图传递您的cors 配置不接受的凭据或自定义标头。你能指出确切的错误吗?
猜你喜欢
  • 2019-09-15
  • 2021-01-13
  • 2021-11-06
  • 1970-01-01
  • 2022-01-21
  • 2022-01-06
  • 1970-01-01
  • 2023-01-19
  • 1970-01-01
相关资源
最近更新 更多