Hi i am facing CORS issue in expressjs and nuxtjs while uploading files in production mode. things works fine on localhost but after i deploy to digital ocean, only one route where i upload file doesn't work.
here are the codes so far
this is app.js
const express = require('express');
const helmet = require('helmet');
const xss = require('xss-clean');
const mongoSanitize = require('express-mongo-sanitize');
const compression = require('compression');
const cors = require('cors');
const passport = require('passport');
const httpStatus = require('http-status');
const config = require('./config/config');
const morgan = require('./config/morgan');
const { jwtStrategy } = require('./config/passport');
const { authLimiter } = require('./middlewares/rateLimiter');
const routes = require('./routes/v1');
const { errorConverter, errorHandler } = require('./middlewares/error');
const ApiError = require('./utils/ApiError');
const app = express();
if (config.env !== 'test') {
app.use(morgan.successHandler);
app.use(morgan.errorHandler);
}
// set security HTTP headers
app.use(helmet());
// parse json request body
app.use(express.json());
// parse urlencoded request body
app.use(express.urlencoded({ extended: true }));
// sanitize request data
app.use(xss());
app.use(mongoSanitize());
// gzip compression
app.use(compression());
// enable cors
app.use(cors());
app.options('*', cors());
// jwt authentication
app.use(passport.initialize());
passport.use('jwt', jwtStrategy);
// limit repeated failed requests to auth endpoints
if (config.env === 'production') {
app.use('/v1/auth', authLimiter);
}
// v1 api routes
app.use('/v1', routes);
// send back a 404 error for any unknown api request
app.use((req, res, next) => {
next(new ApiError(httpStatus.NOT_FOUND, 'Not found'));
});
// convert error to ApiError, if needed
app.use(errorConverter);
// handle error
app.use(errorHandler);
module.exports = app;
this is upload.route.js inside routes folder
const express = require('express');
const uploadController = require('../../controllers/uploads.controller')
const router = express.Router();
router.post('/image', uploadController.setProductImages)
router.post('/image/activity', uploadController.uploadActivityImage)
module.exports = router;
this is index.js inside routes folder
const express = require('express');
const uploadRoute = require('./upload.route');
const config = require('../../config/config');
const router = express.Router();
const defaultRoutes = [
{
path: '/uploads',
route: uploadRoute
}
];
defaultRoutes.forEach((route) => {
router.use(route.path, route.route);
});
module.exports = router;
this is the error i am getting when i upload files.
cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at
https://v1api.thetripclub.com/v1/uploads/image/activity. (Reason: CORS
header ‘Access-Control-Allow-Origin’ missing). Status code: 504.
XHRPOSThttps://***.*******.com/v1/uploads/image/activity
CORS Missing Allow Origin
Related
Okay so i just started building an api using Node. Normally, before i even start, i test it in the postman using dummy data to make sure all the routes are working fine but i never tested it on the browser until today. It brings out the dummy data all fine in the postman but when I put in the same route i used in the postman on the browser tab, it just brings out my custom error message "Route does not exist". Why is this happening?
This is my routes/auth.js
const express = require('express')
const router = express.Router()
const {upload} = require('../utils/multer')
const { register, login } = require('../controllers/auth')
router.post('/register', upload.single('picture'), register)
router.post('/login', login)
module.exports = router
This is my controllers/auth.js:
const register = async (req, res) => {
res.send('register')
}
const login = async (req, res) => {
res.send('login')
}
module.exports = {register, login}
This is my app.js:
require('dotenv').config()
require('express-async-errors');
const bodyParser = require('body-parser')
const cors = require('cors')
const multer = require('multer')
const helmet = require('helmet') //helps you secure your Express apps by setting various HTTP headers.
const morgan = require('morgan')
const path = require('path')
const express = require('express');
const app = express();
/* CONFIGURATIONS */
app.use(helmet());
app.use(helmet.crossOriginResourcePolicy({ policy: "cross-origin" }));
app.use(morgan("common"));
app.use(bodyParser.json({ limit: "30mb", extended: true }));
app.use(express.urlencoded({ limit: "30mb", extended: true }));
app.use("/assets", express.static(path.join(__dirname, "public/assets")));
//routers
const authRouter = require('./routes/auth')
// error handlers
const notFoundMiddleware = require('./middleware/not-found');
const errorHandlerMiddleware = require('./middleware/error-handler');
//middleware
app.use(express.json());
app.use(cors());
//routes
app.use('/api/v1/auth', authRouter)
//errors
app.use(notFoundMiddleware);
app.use(errorHandlerMiddleware);
//database
const connectDB = require('./db/connect');
const port = process.env.PORT || 5000;
const start = async () => {
try {
await connectDB(process.env.MONGO_URI);
app.listen(port, () =>
console.log(`Server is listening on port ${port}...`)
);
} catch (error) {
console.log(error);
}
};
start();
Please note that i do not understand what most of these configurations do, not very well anyways. i have tried to remove them though but the problem was still there.
I am assuming you are trying to access /login or /register route from browser search bar something like this http://host:port/login. With this browser will send GET /login request but /login is a POST method route that is the reason you are getting Route not found
When you send request from your browser then by default it will send GET request and your app is not handling GET requests.
You are handling POST requests for /register and /login routes.
Ive set user cookie as a jwt token in the browser and it is setted up successfully but when I try to get that cookie using req.cookies it gives me undefined and [object: null prototype] {}. Heres my code
exports.isAuthenticated = asyncErrorHandler(async (req, res, next) => {
//fetching the jwt token from the cookie
const { token } = req.cookies;
console.log(req.cookies);
if (!token) return next(new ErrorHandler("plz log in first ", 400));
//verifying the given token matches the jwt stored token
const decodedData = jwt.verify(token, process.env.JWT_SECRET);
req.user = await userModel.findById(decodedData.id);
next();
});
this is my express app.js file
const express = require("express");
const errorMiddleware = require("./middleware/error");
const cookieParser = require("cookie-parser");
const bodyparser = require("body-parser");
const fileupload = require("express-fileupload");
const cors = require("cors");
const app = express();
app.use(cookieParser());
app.use(express.json());
app.use(bodyparser.urlencoded({ extended: true }));
app.use(fileupload());
app.use(
cors({
credentials: true,
origin: "http://127.0.0.1:5173",
optionsSuccessStatus: 200,
})
);
// Route Imports
const productRoutes = require("./routes/productRoutes");
const userRoutes = require("./routes/userRoutes");
const orderRoutes = require("./routes/orderRoute");
const bodyParser = require("body-parser");
app.use("/api/v1", productRoutes);
app.use("/api/v1/user", userRoutes);
app.use("/api/v1", orderRoutes);
//error HAndler Middleware
app.use(errorMiddleware);
module.exports = app;
Ive tried cookie-parseer and also had cors in my express app file. ive set the cookie key as token
the req.cookies isn't the right way to get cookies
If you want to get cookies it is in the header so you must get cookies from header from the request like this :
console.log(req.headers.cookie)
I have an express API and there is a post route to create categories and products. But the post route is not functioning correctly. When I send a request to post route it's not reaching the route. However, when I send to get: /admin route it's reaching the route.
const express = require('express');
const { Category } = require('../models/categories');
const { Product } = require('../models/products');
const catchAsync = require('../utils/catchAsync')
const adminRouter = express.Router();
//Reaching this route
adminRouter.get('/', catchAsync(async(req, res)=>{
res.send({msg: 'HELLO'})
}))
//Not reaching at all
adminRouter.post('/category/create', catchAsync(async (req, res)=>{
const categoryData = req.body
console.log(req.body);
const category = await Category.create(categoryData);
res.status(201).json(category)
}))
adminRouter.post('/product/create', catchAsync(async(req, res)=>{
const productData = req.body
const product = await Product.create(productData);
res.status(201).json(product);
}))
module.exports = {adminRouter}
And this is my app.js
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const { adminRouter } = require('./routes/admin');
const app = express();
app.use(bodyParser.json({limit: "30mb", extended: true}))
app.use(bodyParser.urlencoded({limit: "30mb", extended: true}))
app.use(cors())
app.use('/admin', adminRouter)
module.exports = {app}
This is what I get when I send request from Postman
As you can see no status code and no response body. However when I send request to get route it's returning correct response.
I am new to React and Node and I'm getting an undefined token in console when I add category I get undefined in the console. I am using cookie-parser.
server.js file:
const express = require('express');
const app = express();
const cors = require('cors');
const morgan = require('morgan');
const cookieParser = require('cookie-parser')
const connectDB = require('./database/db');
const authRoutes = require('./routes/auth');
const categoryRoutes = require('./routes/category');
//middleware
app.use(cors());
//dev specifies it is for development
app.use(morgan('dev'));
//express.json allows us to parse incoming request in json in the format of a json
app.use(express.json());
app.use(cookieParser());
app.use('/api/auth', authRoutes);
//route for category
app.use('/api/category', categoryRoutes);
connectDB();
app.get('/', (req,res) => {
res.send('Inside Server');
});
const port = process.env.PORT || 5000;
app.listen(port, ()=>console.log(`Listening on port ${port}`));
category.js (controller file)
exports.create = (req,res) => {
setTimeout(()=> {
res.json({
successMessage: `${req.body.category} was created!`
});
}, 5000);
};
category.js (routes file)
const express = require('express');
const router = express.Router();
const categoryController = require('../controllers/category');
const { authenticateJWT } = require('../middleware/authenticator');
router.post('/', authenticateJWT , categoryController.create);
module.exports = router;
authenticator.js (middleware file)
const jwt = require('jsonwebtoken');
const { jwtSecret } = require('../config/keys');
exports.authenticateJWT = (req, res, next) => {
const token = req.cookies.token;
console.log(token);
}
keys.js file
//it is gonna tell us/ signifying if we are live if in develoopment or in production
const LIVE = false;
if (LIVE) {
module.exports = require('./prod.js');
} else {
module.exports = require('./dev.js');
}
Console screen:
Instead of undefined i should be getting token.
Any help will be highly appreciated.
Thanks!
Is there a token Cookie available? (You can check using the inspector of your browser, normally in the „application“ tab. If you are sending the request using any tools like postman, curl, wget, …, you have to set the cookie first.)
Was the cookie available on any other routes? What’s the difference between these routes and the category route? Is it possible that your cookie is constrained to a specific path, e.g. to /api/auth? If so, adjust the path in res.cookie.
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
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".