简体   繁体   中英

How to solve CORS error in NodeJS independent of CORS middleware

I am facing a CORS error when trying to make a request from the client to a node server. I want to solve the issue independent of the CORS middleware. Here is the server-side code. Please let me know if I am missing something. Thanks.

const express = require("express");
const app = express();

app.get("/", (req, res) => {
  res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
  res.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT");
  res.setHeader("Access-Control-Allow-Headers", "application/json");
  res.send("<h1>Server is running at port 3000!<h1>");
});
app.listen(3000);

The error on the console:

Access to fetch at 'http://localhost:3000/' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

The error message you get on the console says this:

Response to preflight request doesn't pass access control check

That means that the type of requests you are sending is not a "simple" request and requires server pre-flight. Pre-flight is where the browser sends an OPTIONS request with some details about the type of request it wants to send. The server then must respond to that OPTIONS request with the right CORs info before the browser will treat the request as approved and send the actual request.

To response to a pre-flight request, you must handle an incoming OPTIONS request (not a GET or POST or PUT, but OPTIONS). This is the browser asking your server if this request would be OK to send. You can read more about pre-flight requests here on MDN . And, you can read about the difference between simple requests and pre-flighted requests here on MDN .

To code your server to accept the pre-flighted request, you could do something like this:

app.options("/", (req, res) => {
  res.setHeader("Access-Control-Allow-Origin", "http://127.0.0.1:5500");
  res.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT");
  res.setHeader("Access-Control-Allow-Headers", "Content-Type");
  res.sendStatus(204);
});

Depending upon what exactly the pre-flighted request is (what content-type, what method, etc...) you may need to specify additional options here. You don't show the code for the request in question here so we can't offer more specific details on that request.

Also, where you have this:

res.setHeader("Access-Control-Allow-Headers", "application/json");

that doesn't really make sense because "application/json" is a content-type, not a header. Perhaps you meant this:

res.setHeader("Access-Control-Allow-Headers", "Content-Type");

Simple Requests

This is all spelled out in one of the above MDN references, but a Simple Request that does not require CORs pre-flight, meets the following criteria:

  • Http method is GET, HEAD or POST
  • Manually set headers on the request (apart from what the browser sets automatically) are no more than Accept , Accept-Language , Content-Language and Content-Type .
  • Content-Type can only be application/x-www-form-urlencoded , multipart/form-data or text/plain

Any request that doesn't meet these simple rules will require pre-flight. So, for example, if you were setting the Content-Type to application/json , that would immediately cause pre-flight because that's not one of the permitted content-types for non-preflighted requests. If your request was a GET, then there's no need to set content-type at all since you aren't sending any content with the request.

const corsOpts = {
  origin: '*',

  methods: [
    'GET',
    'POST',
  ],

  allowedHeaders: [
    'Content-Type',
  ],
};

app.use(cors(corsOpts));

OR you can use

app.use(function(req, res, next) {
    res.setHeader('Access-Control-Allow-Origin', '*');
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
    res.setHeader('Access-Control-Allow-Credentials', true);
    next();
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM