CORS issue with Express Router end points - javascript

I have a react app that is making a REST to a an express node server.
The express router defines a bunch of rest endpoints.
When I hit the endpoints in the express router using postman, it works fine.
When I hit the endpoint with me react app, it doesn't. I'm seeing 400 error when my react app makes the call using axios.
This is what my index.js looks like:
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const cors = require("cors");
const app = express();
app.use(bodyParser.urlencoded({ extended: false }));
// server.use(bodyParser.json());
app.use(cors());
// app.options("*", cors());
const UserModel = require("./models/User");
mongoose
.connect(
"mongodb"
)
.then(() => console.log("SUCESSFULLY connected to MongoDB!"))
.catch((error) => console.log(`FAILED tot connect to MongoDB: ${error}`));
require("./auth/localStrategyAuth");
const authRoutes = require("./routes/authRoutes");
app.use("/v1", authRoutes);
// app.post("/", (req, res) => {
// res.send("Hello World!");
// });
// app.post("/v1/signup", (req, res) => {
// console.log("lol");
// });
// app.use(express.json());
const PORT = 5000;
app.listen(PORT, () =>
console.log(`ui-rest listening on port localhost:${PORT}`)
);
user.js
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const { Schema } = mongoose;
const UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true,
},
password: {
type: String,
required: true,
},
});
const UserModel = mongoose.model("user", UserSchema);
module.exports = UserModel;
authRoutes.js
const express = require("express");
const passport = require("passport");
const jwt = require("jsonwebtoken");
const JWTstrategy = require("passport-jwt").Strategy;
//We use this to extract the JWT sent by the user
const ExtractJWT = require("passport-jwt").ExtractJwt;
const router = express.Router();
// When the user sends a post request to this route, passport authenticates the user based on the
// middleware created previously
router.post(
"/signup",
passport.authenticate("signup", { session: false }),
async (req, res, next) => {
res.json({
message: "Signup successful",
user: req.user,
});
}
module.exports = router;
localStrategyAuth.js
const passport = require("passport");
const localStrategy = require("passport-local").Strategy;
const UserModel = require("../models/User");
//Create a passport middleware to handle user registration
passport.use(
"signup",
new localStrategy(
{
usernameField: "email",
passwordField: "password",
},
async (email, password, done) => {
try {
// Save the information provided by the user to the the database
const user = await UserModel.create({ email, password });
// Send the user information to the next middleware
return done(null, user);
} catch (error) {
done(error);
}
}
)
);
This is what my express router looks like:
const express = require("express");
const router = express.Router();
router.post(
"/signup",
passport.authenticate("signup", { session: false }),
async (req, res, next) => {
res.json({
message: "Signup successful",
user: req.user,
});
}
);
module.exports = router;
What am I missing? I've set up CORS in the index.js file. I just can't see where I'm going wrong. Why cant my react app hit the express router endpoints.
If I have a normal express endpoint, then my react app is able to hit those endpoints. For example, the endpoint below works fine when my react app hits it.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
app.post("/", (req, res) => {
res.send("Hello World!");
});
const PORT = 5000;
app.listen(PORT, () =>
console.log(`listening on port localhost:${PORT}`)
app.post("/someSignup", (req, res) => {
console.log("signup");
});
I've also tried things like with no luck:
const authRoutes = require("./routes/authRoutes");
authRoutes.use(cors());
Here is what my react code looks like when it submits the rest call:
// axios setup
axios.create({
baseURL: "http://localhost:5000",
// headers: {
// "Content-Type": "application/json",
// },
});
// Handle submit
handleSubmit = async (event) => {
event.preventDefault();
const newUserData = {
// firstName: this.state.firstName,
// lastName: this.state.lastName,
email: this.state.email,
password: this.state.password,
};
const result = await axios.post("/v1/signup", newUserData);
console.log(result);
};
Here is a screenshot of headers tab on chrome console
Here is a screenshot of response tab on chrome console
Here is a screenshot of the request

400 means bad request, your problem isn't about with cors.
You didn't setup your api to handle JSON data which react sends, so it can't read your request.body and gives 400-Bad Request.
So you need to add this line:
app.use(bodyParser.json());
Also in the current versions of express, body parser isn't required , it comes with express. So you can use it like this:
app.use(express.json());
The reason it worked with postman is that you sent the data in x-www-form-urlencoded.

you can use check my code for cors error.
const express = require('express');
var mongoose = require('mongoose');
const bodyParser = require('body-parser');
var morgan = require('morgan');
var cors = require('cors')
const app = express();
// CORS Middleware
app.use(cors());
// Logger Middleware
app.use(morgan('dev'));
// Bodyparser Middleware
app.use(bodyParser.json());
const MongoClient = require('mongodb').MongoClient;
const uri = "uri";
const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });
client.connect(err => {
console.log('MongoDB Connected...')
const collection = client.db("dbname").collection("collectionname");
app.post('/name', (req, res) => {
collection. insertOne({ name: req.body.name })
res.send("data added")
});
});
const port = process.env.PORT || 5000;
app.listen(port, function () {
console.log(`Example app listening on port ${port}`);
});

You need to register the cors middleware into express app.
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
app.use(cors());
app.post("/", (req, res) => {
res.send("Hello World!");
});
const PORT = 5000;
app.listen(PORT, () => console.log(`listening on port localhost:${PORT}`)

Related

CRUD - I can't insert data using express and mongodb

I am trying to insert a category in the database following the instructions of a course I am taking and I am unable to insert it with the create method. It shows ... loading in Postman and nothing happens and no error message appears on the console. Here are my files.
app.js
const express = require('express')
const mongoose = require('mongoose')
const morgan = require('morgan')
const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
const expressValidator = require('express-validator')
require('dotenv').config()
//import routes
const authRoutes = require('./routes/auth')
const userRoutes = require('./routes/user')
const categoryRoutes = require('./routes/category')
// app
const app = express()
// db
mongoose.connect(process.env.DATABASE, {
useNewUrlParser: true,
useCreateIndex: true
})
.then(() => console.log('DB Connected'))
// middlewares
app.use(morgan('dev'))
app.use(bodyParser.json())
app.use(cookieParser())
app.use(expressValidator())
// routes middleware
app.use('/api', authRoutes)
app.use('/api', userRoutes)
app.use('/api', categoryRoutes)
const port = process.env.PORT || 8000
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
routes/category.js
const express = require('express')
const router = express.Router()
const { create } = require('../controllers/category')
const { requireSignin} = require('../controllers/category')
const { userById } = require('../controllers/user')
router.post('/category/create/:userId', function(req, res){
requireSignin,
create
});
router.param("userId", userById)
module.exports = router
controllers/category.js
const Category = require("../models/category")
const { errorHandler } = require("../helpers/dbErrorHandler")
exports.create = (req, res) => {
const category = new Category(req.body)
category.save((err, data) => {
if(err) {
return res.status(400).json({
error: errorHandler(err)
})
}
res.json({ data })
})
}
models/category.js
const mongoose = require('mongoose')
const categorySchema = new mongoose.Schema(
{
name: {
type: String,
trim: true,
required: true,
maxlength: 32
}
},
{ timestamps: true }
);
module.exports = mongoose.model('Category', categorySchema)
In order to make sure that data is actually being returned, your create function needs to be asynchronous. Adding async/await to the save function should confirm that you are properly saving the data to the database before returning.
It appears you have an error in your route setup. I assume requireSignin and create should be middleware functions.
So instead of
router.post('/category/create/:userId', function(req, res){
requireSignin,
create
});
you should try this
router.post('/category/create/:userId', requireSignin, create);
// assuming 'create' is the last one, since you are ending the request there
// also assuming that 'requireSignin' is setup as middleware, calling next function

Getting TypeError: User is not a constructor when testing user add with API

I am trying to make my backend work with MongoDB ATLAS.
I'm using express, mongoose and node.js for my tests and when I am trying to test my API routes (in this case to add a user)
The code I have is the following:
users.js
const router = require('express').Router();
const { Router } = require('express');
let User = require('../models/user.model');
router.route('/').get((req, res) => {
User.find()
.then(users => res.json(users))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req, res) => {
const username = req.body.username;
const newUser = new User({username});
newUser.save()
.then(() => res.json('User added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router
user.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlength: 3
},
}, {
timestamps: true,
});
const User = mongoose.model('User', userSchema);
module.exports = User;
server.js
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true }
);
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB database connection established successfully");
})
const exercisesRouter = require('./routes/exercises');
const usersRouter = require('./routes/users');
app.use('/exercises', exercisesRouter);
app.use('/users', usersRouter);
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
});
When I am testing this with postman via a POST I get the following error: I am getting the following error: TypeError: User is not a constructor
The post is done to http over port 5000 with raw json body as "username": "blahblahblah"
Can you help with this maybe?
I am not sure what happened but today I cut and pasted back all the code and the API started to work just fine. Now I can add users without any problems.
Could be a glitch but not sure at this point.

Node.js REST endpoint not catching parameters passed from axios request

I'm making a POST request from a React front-end using axios to an endpoint to save some data to my DB (MongoDB). I'm getting an error that one cannot read property 'name' of undefined. I think that's occurring because req.body is undefined but I can't understand what's wrong with my axios request. I logged all the parameters and they are there (not undefined). The axios request and the endpoint are written below. Any help will be appreciated. Thanks!
Axios Request
const uploadElement = async (name, HTMLCode, JSCode, CSSCode, screenshot) => {
console.log(name)
try {
await axios({
method: 'post',
url: '/api/elements',
data: {
name: name,
HTMLCode,
JSCode,
CSSCode,
screenshot
}
});
} catch (e) {
console.log(e);
}
}
Endpoint for POST Request
router.post("/", upload.single("screenshot"), async (req, res) => {
try {
const newElement = new Element({
name: req.body.name,
JSCode: req.body.JSCode,
HTMLCode: req.body.HTMLCode,
CSSCode: req.body.CSSCode,
screenshot: req.file.buffer,
});
await newElement.save();
res.send("Data uploaded successfully!");
} catch (e) {
console.error(e);
}
});
Server.js
const express = require("express");
const passport = require("passport");
const session = require("express-session");
const cors = require('cors');
const elementRouter = require("./routes/elementRoute");
const authRouter = require("./routes/authRoute");
const connectDB = require("./config/db");
const app = express();
const port = process.env.PORT || 5000;
connectDB();
app.use(
session({
secret: "googleOAuth",
resave: false,
saveUninitialized: true,
})
);
app.use(cors());
// Passport Config
require("./config/passport")(passport);
app.use(passport.initialize());
app.use(passport.session());
app.use("/api/elements", elementRouter);
app.use("/api/auth", authRouter);
app.listen(port, () => {
console.log(`Server is up on port ${port}`);
});
You need to install and require body-parser in your serverside code
First run npm i --save body-parser
Then require it like this
const bodyParser = require("body-parser");
Then use it after you declare your app ( after this line const app = express();)
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
This makes the data of your request available in req.body

Why does save function in express not work?

This is my first day in express. I was trying to create a simple route but my save function doesn't seem to work. I tried looking at similar questions posted on stackoverflow but couldn't make it. Any help will be appreciated.
const express = require("express");
const router = express.Router();
const Post = require("../models/Post");
//ROUTES
router.post('/', (req, res) => {
const post = new Post({
title: req.body.title,
description: req.body.description
})
post.save()
.then(data => {
res.json(data);
})
.catch(err => {
res.json(err);
});
});
module.exports = router;
And here is my model.
const mongoose = require("mongoose");
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
}
});
module.exports = mongoose.model('Posts',PostSchema);
app.js code
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
require("dotenv/config");
//IMPORT ROUTES
const postsRoute = require("./routes/posts");
//MIDDLEWARE - Function that always execute when routes are being hit.
app.use(bodyParser.json())
app.use('/posts', postsRoute)
//app.use('/users', usersRoute)
//ROUTES
app.get('/', (req, res) => {
res.send("We are on home");
});
//CONNECT TO DB
mongoose.connect(
process.env.DB_CONNECTION,
{ useNewUrlParser: true },
() => {
console.log("DB Connected!!")
})
//How do we start listening to the server
app.listen(3000);
My postman query -
Postman Response -
Please let me know if you need any more information.
your app.js should be :
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
require("dotenv/config");
//MIDDLEWARE - Function that always execute when routes are being hit.
app.use(bodyParser.json())
mongoose.connect(process.env.DB_CONNECTION, { useNewUrlParser: true }, function(err) {
if (err) {
console.error('System could not connect to mongo server')
console.log(err)
process.exit()
} else {
console.log('System connected to mongo server')
}
});
//ROUTES
app.get('/', (req, res) => {
res.send("We are on home");
});
//IMPORT ROUTES
const postsRoute = require("./routes/posts");
app.use('/posts', postsRoute)
app.listen(3000);
also add console log in router to check req.body :
router.post('/', (req, res) => {
console.log('req.body===',req.body);
...
});

Send Arraydata from the from react to node. and save it in mongoose

I am trying to send an array from react using axios to my Node.js file, however I am getting an status 404 error.
My profileSchema as follows:
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
// Create Schema
const ProfileSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: "users"
},
preference: [
{
type: String
}
],
date: {
type: Date,
default: Date.now
}
});
module.exports = Profile = mongoose.model("profile", ProfileSchema);
I want to send an array to the back end with an axios request.
for example
tempArray=["Chocoloate","Vanilla","Strawberry"]
and the axios request I make is
axios
.post('/api/profile/register', tempArray)
.then(res => console.log(res.data))
.catch(err => console.log(err));
My profile.js look list this. I also have body-parse and all installed.
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const passport = require("passport");
const Profile = require("../../models/Profile");
// Load User Model
const User = require("../../models/User");
router.get("/test", (req, res) => res.json({ msg: "Profile Works" }));
// #route POST api/profile
// #desc Create or edit user profile
// #access Private
router.post(
"/register",
(req, res) => {
console.log(req);
var list = req.body;
console.log(list);
}
);
However, I am still getting 404 errors and not being able to save the array to the backend
index.js file
const express = require("express");
const mongoose = require("mongoose");
const bodyParser = require("body-parser");
const passport = require("passport");
const users = require("./routes/api/users");
const profile = require("./routes/api/profile");
const posts = require("./routes/api/posts");
const issues = require("./routes/api/issues");
const mp = require("./routes/api/mp");
const app = express();
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// DB Config
const db = require("./config/keys").mongoURI;
// Connect to MongoDB
mongoose
.connect(db)
.then(() => console.log("MongoDB Connected"))
.catch(err => console.log(err));
// Passport middleware
app.use(passport.initialize());
// Passport Config
require("./config/passport")(passport);
// Use Routes
app.use("/api/users", users);
app.use('/api/profile', profile);
app.use("/api/posts", posts);
app.use("/api/issues", issues);
app.use("/api/mp", mp);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port}`));
Always try sending the post body as an object.
tempArray = ['a', 'b', 'c']
axios
.post('/api/profile/register', {tempArray: tempArray})
.then(res => console.log(res.data))
.catch(err => console.log(err));
and the body params in the router.post as
router.post('/register/', function(req, res,next) {
const tempArray = req.body.tempArray;
//perform your query operations here and pass tempArray as params to your query
})

Categories