0

I'm trying to send a POST request to my Express server, but it always throws this error

Access to fetch at 'http://localhost:4000/users/sign-up' from origin 'http://localhost:3000' 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.

And this is how I setup my server "using TypeScript"

import express, { Application } from 'express';
import * as dotenv from 'dotenv';
import { databaseConnect, serverConnect } from './modules/connections';
import bodyParser from 'body-parser';
import cors from 'cors';
import devicesRouter from './routes/dashboard';
import usersRouter from './routes/users';
import announcementsRouter from './routes/announcements';
import ordersRouter from './routes/orders';

// Initializing express
const app: Application = express();

// Server configurations
dotenv.config();
await databaseConnect();
app.use(express.json());
app.use(bodyParser.json());
app.use(cors({ origin: "http://localhost:3000", credentials: true }));

// Defining server routes
app.use('/devices', devicesRouter);
app.use('/users', usersRouter);
app.use('/announcements', announcementsRouter);
app.use('/orders', ordersRouter);

// Connecting server
serverConnect();

And in my client I'm using the fetch API to send the post request

const response = await fetch("http://localhost:4000/users/sign-up", { method: "POST", headers: { "Accept": "application/json", "Content-Type": "application/json", "Access-Control-Allow-Origin": "http://localhost:3000" }, body: JSON.stringify(signUpData) });

I have seen many videos about fixing this error just by installing the cors package, but somehow it didn't work for me.

I tried to reinstall both the cors and @types/cors packages but nothing changes.

I also tried using

app.use(cors({ origin: "http://192.168.1.3:3000", credentials: true }));

instead of

app.use(cors({ origin: "http://localhost:3000", credentials: true }));

but it did't work as well.

  • you're fetching from port 4000, but you set the cors origin to 3000 - was this intended? – Alfie Feb 27 '23 at 13:14
  • 1
    @Alfie The origin is where the request originates from, not the destination. – Dave Newton Feb 27 '23 at 13:16
  • Can you try adding this before any route. app.options('*', cors()) – CodeThing Feb 27 '23 at 13:16
  • @Yogi Unfortunately, it doesn't. if you take a look at my request headers you can see the "Access-Control-Allow-Origin" property set to "http://localhost:3000" –  Feb 27 '23 at 13:17
  • 1
    CORS and localhost don't play nicely together. [Why does my http://localhost CORS origin not work?](https://stackoverflow.com/questions/10883211/why-does-my-http-localhost-cors-origin-not-work) – Daniel Beck Feb 27 '23 at 13:18
  • @DaveNewton Yes, my bad, I suppose really I meant just to double check this (is OP trying to execute the code from port 3000, 4000, or other?) – Alfie Feb 27 '23 at 13:19
  • @Alfie I tried using an asterisk symbol instead of defining a specific route but It did't work –  Feb 27 '23 at 13:20
  • @CodeThing Just tried it but unfortunately it did't work –  Feb 27 '23 at 13:21
  • I think @DanielBeck's comment is the answer. I seem to recall having a similar issue when using Chrome in the past. – Alfie Feb 27 '23 at 13:24
  • Your error message says, it did not found Access-Control-Allow-Origin on the request header. So there is definitely something wrong with sending request. Can you try deleting that header origin. Is it working from Postman? – CodeThing Feb 27 '23 at 13:26
  • @Alfie I tried @DenielBeck's answer `app.use(cors({ origin: "http://192.168.1.3:3000", credentials: true })); ` but I'm still getting the same error. –  Feb 27 '23 at 13:28
  • @CodeThing Yes it does, I tried it using Postman and Thunder Clinet VS code extension and it's working fine. –  Feb 27 '23 at 13:30
  • @SaifEssam Are you confirming it works when testing not using Chrome? – Alfie Feb 27 '23 at 13:38
  • 1
    @SaifEssam - a few things. 1. The `Access-Control-Allow-Origin` header is meant to be a **Response** header, not a request one. It makes no difference if you include it in your request. 2. I think it's working with HTTP clients because they don't send an `origin` header at all. 3. try [editing your hosts file](https://www.addictivetips.com/windows-tips/modify-the-hosts-file-on-windows-10/) and add a different domain for `127.0.0.1`, for example - `my_app`. Then set the `Allow-Origin` in the node.js code to be `my_app:3000` and access `my_app:4000`. **Be sure to restart Node between changes.** – Yarin_007 Feb 27 '23 at 13:41
  • or add different domains that point to `127.0.0.1`. makes no difference. – Yarin_007 Feb 27 '23 at 13:43
  • Maybe this will help: https://stackoverflow.com/questions/35588699/response-to-preflight-request-doesnt-pass-access-control-check. Also is there any reason you set credentials option to true? – CodeThing Feb 27 '23 at 13:44
  • Drop this `Access-Control-Allow-Origin` header from your request. – jub0bs Feb 27 '23 at 13:45
  • @Alfie Yes it works out side chrome. –  Feb 27 '23 at 13:47
  • @Yarin_007 I have updated the question and I included your answer. –  Feb 27 '23 at 13:48
  • You'll need to explicitly allow the `Content-Type` header in your CORS configuration. – jub0bs Feb 27 '23 at 14:06
  • I have solved it and posted the answer, it was my fault. Thank you all. –  Feb 27 '23 at 14:36
  • 1
    @Yogi At the app level it’s enabled by default: https://expressjs.com/en/resources/middleware/cors.html#enabling-cors-pre-flight – Dave Newton Feb 27 '23 at 14:53

2 Answers2

0

I have solved it, the problem was in the serverConnect() function. I was initializong a new instace of express when I call the function and that was the reason why I get the errors.

I was doing it like this

export function serverConnect() {
    const app: Application = express(); // <== This line was is what causes the error

    try {
        app.listen(4000, () => console.log("✅  Server is connected successfully"));
    } catch (error) {
        console.error("  Error starting the server\n", error);
    }
}

I changed it to this and it works fine

export function serverConnect(app: Application) {
    try {
        app.listen(4000, () => console.log("✅  Server is connected successfully"));
    } catch (error) {
        console.error("  Error starting the server\n", error);
    }
}

Thanks for your contributions. it was my fault from beginning.

-1

You can use express cors middleware: https://expressjs.com/en/resources/middleware/cors.html

var corsOptions = {
  origin: '*', // <-- this, as mentioned in the docs linked above, or change it to whatever your origin is
}
dude
  • 1
  • 1