Home > database >  CORS preflight request error on angular app deployed on heroku with node express backend
CORS preflight request error on angular app deployed on heroku with node express backend

Time:01-17

I have deployed an angular app on heroku (with the frontends and backend separated in multiple heroku apps) for a project at school and I'm stuck on an issue with CORS preflight requests.

Everytime I send a request to the backend I get the following error

Access to XMLHttpRequest at 'https://playlist-manager-backend.herokuapp.com/user/authenticate' from origin 'https://playlist-manager-admin.herokuapp.com' 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.

Here is the code of my server.js pushed on the backend app (playlist-manager-backend)

const express = require("express");
const { connect: dbconnect } = require("./src/db");
const { apiPort } = require("./src/config");
const routes = require("./src/routes");
const bodyParser = require("body-parser");
// Connect to the database
dbconnect();

// Create the server
const app = express();

// const cookieParser = require("cookie-parser");
// app.use(cookieParser());
app.use(bodyParser.json({ limit: "5mb" }));
// app.get("/", (req, res) => res.send("Hello World"));
const cors = require("cors");

/*let whitelist = ["https://playlist-manager-admin.herokuapp.com/","https://playlist- manager-user.herokuapp.com/"];*/

const corsOptions = {
    origin: ["https://playlist-manager-admin.herokuapp.com/", "https://playlist-manager-user.herokuapp.com/"],
    preflightContinue:false,
    credentials: true
}

app.use(cors(corsOptions));


app.use("/", routes);
app.use(express.static("./adverts"));

app.listen(apiPort, () => {
    console.log(`Server is listening on port ${apiPort}`);
});

The routes to the backend functions are defined using router in the routes.js file like this.

const express = require("express");
const router = express.Router();

const userRoute = require("../user/user.route");
const playlistRoute = require("../playlist/playlist.route");
const videoRoute = require("../video/video.route");
const annonceUploadRoute = require("../annoncesUpload/annoncesUpload.route");
const historyRoute = require("../history/history.route");
const advertiserRoute = require("../advertiser/advertiser.route");

router.use("/user", userRoute);
router.use("/playlist", playlistRoute);
router.use("/video", videoRoute);
router.use("/annoncesUpload", annonceUploadRoute);
router.use("/history", historyRoute);
router.use("/annonceur", advertiserRoute);

module.exports = router;

Here is an example of how routes are implemented :

router.post("/getById", async function(req, res) {
     const request = {
         _id: req.body._id,
     };
     const result = await bo.getById(request);
     res.send(result);
});

The frontend sends a post request to the backend using a service implemented like this :

import { Injectable } from '@angular/core';
import {HttpClient} from '@angular/common/http';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';

export interface BackendData {
  success: string ;
  data: any ;
}

@Injectable({
  providedIn: 'root'
})
export class MessageService {

  constructor(private http:HttpClient) { }

  sendMessage(Url:string, data:any): Observable<BackendData> {
    const serveur = environment.server   Url ;
    
    return this.http.post<BackendData>(
      serveur,
      data,
      {withCredentials: true}
    );
  }
}

I tried every solutions I saw online but I always got the same error or another error related to CORS policy. I need help figuring out this behavior. The app was working fine locally when I specified localhost with cors package like in the documentation.

Edit : I removed slashes on the URL's and my server.js is like this :

const express = require("express");
const { connect: dbconnect } = require("./src/db");
const { apiPort } = require("./src/config");
const routes = require("./src/routes");
const bodyParser = require("body-parser");
// Connect to the database
dbconnect();

// Create the server
const app = express();

// const cookieParser = require("cookie-parser");
// app.use(cookieParser());
app.use(bodyParser.json({ limit: "5mb" }));
// app.get("/", (req, res) => res.send("Hello World"));
const cors = require("cors");

/*let whitelist = ["https://playlist-manager-admin.herokuapp.com/", "https://playlist-manager-user.herokuapp.com/"];*/

const corsOptions = {
  origin: ["https://playlist-manager-admin.herokuapp.com", "https://playlist-manager-user.herokuapp.com"],
  credentials: true
}

app.use(cors(corsOptions));


app.use("/", routes);
app.use(express.static("./adverts"));

app.listen(apiPort, () => {
    console.log(`Server is listening on port ${apiPort}`);
});

This is the network tab after sending the request

This is the xhr request shown in the network tab

This is the preflight request in the network tab

CodePudding user response:

Thanks to jubObs comments I managed to fix this. The source of the problem was that the backend server wasn't starting which was causing a 503 status. I forgot to add the file defining the credentials for the database connections which caused the backend to fail before adding the headers.

here is the new server.js code :

const express = require("express");
const { connect: dbconnect } = require("./src/db");
const { apiPort } = require("./src/config");
const routes = require("./src/routes");
const bodyParser = require("body-parser");
// Connect to the database
dbconnect();

// Create the server
const app = express();

// const cookieParser = require("cookie-parser");
// app.use(cookieParser());
app.use(bodyParser.json({ limit: "5mb" }));
// app.get("/", (req, res) => res.send("Hello World"));
const cors = require("cors");

/*let whitelist = ["https://playlist-manager-admin.herokuapp.com/", "https://playlist-manager-user.herokuapp.com/"];*/

const corsOptions = {
   origin: ["https://playlist-manager-admin.herokuapp.com", "https://playlist-manager-user.herokuapp.com"],
   credentials: true
}

app.use(cors(corsOptions));


app.use("/", routes);
app.use(express.static("./adverts"));

app.listen(apiPort, () => {
   console.log(`Server is listening on port ${apiPort}`);
});

The database connection was using dotenv and the .env file that was defining the database credentials wasn't present in the main branch so I pushed it. To figure this out I checked the application logs on heroku which are in "more" and "view logs".

  •  Tags:  
  • Related