React beginner here and I am using axios to send the body from my form in my frontend. I did a console.log on the server side and this is what I see in the request.body.
req.body {
'{"body":"{\\"firstName\\":\\"daf\\",\\"lastName\\":\\"afa\\",\\"address\\":\\"af\\",\\"phoneNumber\\":\\"123-933-6177\\",\\"email\\":\\"asfa\\",\\"facilityName\\":\\"afs\\",\\"isSeller\\":false}"}': ''
}
class where I print the bad String above
checkIfDuplicateEmailAndFacilityNameOnSignUp = (req, res, next) => {
// get the customer name
console.log("request", req.body.firstName);
const updatedBody = JSON.parse(req.body);
console.log(updatedBody);
Customer.findOne({
where: {
email: req.body.email
}
}).then(customerEmail => {
if (customerEmail) {
res.status(400).send({
message: "This email is already in use"
});
return;
}
Customer.findOne({
where: {
facilityName: req.body.facilityName
}
}).then(facilityname => {
if (facilityname) {
res.status(400).send({
message: "Facility exists already exists"
});
return;
}
next();
});
});
};
This is my function to post from the front end
const onFormSubmit = (event) => {
event.preventDefault();
const formBody = {
...this.state,
};
axios({
method: "POST",
url: "http://localhost:3000/api/auth/signup",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: {
body: formBody,
},
}).then((response) => {
console.log("response", response);
console.log("response data", response.data);
});
console.log("form submission done");
};
state object
state = {
firstName: "",
lastName: "",
address: "",
phoneNumber: "",
email: "",
facilityName: "",
isSeller: false,
};
this is my node server.js file
const express = require("express");
const bodyParser = require("body-parser");
const app = express();
app.use(bodyParser.json());
app.use(
cors({
origin: "*",
})
);
app.use(
bodyParser.urlencoded({
extended: true,
})
);
require('./app/routes/authRoutes')(app);
require('./app/routes/customerRoutes')(app);
const PORT = 3000;
app.listen(PORT, () => {
console.log(`Now listening on port ${PORT}`);
});
db.sequelize.sync({
force: true
})
.then(() => {
console.log("Dropping and Resync DB");
initial();
});
// creates roles in database for us
function initial() {
Role.create({
id: 1,
roleType: "buyer"
});
Role.create({
id: 2,
roleType: "seller"
});
};
I tried using JSON.parse() but I get an exception with the message Unexpected token o in JSON at position 1. Any idea on how I can go about parsing this?
Update 1:
After changing per #Bravo answer the body looks like this now
body: {
firstName: 'safds',
lastName: 'asf',
address: 'adfs',
phoneNumber: '404-932-6177',
email: 'asdf',
facilityName: 'afs',
isSeller: false
}
Might be a silly question but how do I access the fields. I tried doing body.firstName or body[0] but I get undefined returned?
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
This is the problem. You're lying about the encoding so Express is running your body through bodyParser.urlencoded instead of bodyParser.json.
Take the custom headers out and just use Axios' defaults.
Related
I'm trying to create an API with Node.JS , express and MySQL for that I decided to use an ORM Sequelize. In short, I wanted to do this properly and avoid going through the CLI to do what I have to do.
The problem being that when I try to send a POST request from insomnia to my API it can't create a user for me, I have the impression that it doesn't understand what I'm sending to it and I I'm quite lost because I don't understand where I messed up..
Roughly I think that my problem comes from the fact that I do not know how to link the different sources of .js file between them..
I'll leave you my code maybe it's going to be obvious in any case I've already torn out a lot of hair 😤
app.js:
const { urlencoded } = require('express');
const express = require('express');
const path = require('path');
const userRoutes = require('./routes/user');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
next();
})
app.use('/api/auth', userRoutes);
module.exports = app;
models/index.js:
const db = require('./database');
const User = require ('./user.js');
const Vehicle = require('./vehicle');
const Service = require('./service');
(async () => {
try {
await db.authenticate();
console.log('Connection has been established successfully.');
await db.sync();
// await db.sync({ alter: true, force: true});
// console.log('All models were synchronized successfully.');
} catch (error) {
console.error('Unable to connect to the database:', error);
} finally {
db.close();
}
})()
User.belongsToMany(Vehicle, { through: 'UserVehicles' });
Vehicle.belongsToMany(User, { through: 'UserVehicles' });
module.exports = { User, Vehicle, Service };
models/database.js:
const { Sequelize } = require('sequelize');
require('dotenv').config();
const db = new Sequelize(
process.env.DB_NAME,
process.env.DB_USER,
process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: process.env.DB_DIALECT,
},
);
module.exports = db;
models/user.js
const { DataTypes, Model } = require('sequelize');
const sequelize = require('./database.js');
const validator = require('validator');
class User extends Model {}
User.init({
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
allowNull: false,
primaryKey: true,
unique: true,
},
firstName: {
type: DataTypes.STRING,
allowNull: false,
},
lastName: {
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
},
phoneNumber: {
type: DataTypes.INTEGER,
allowNull: false,
unique: true,
},
password: {
type: DataTypes.STRING,
allowNull: false,
},
birthday: {
type: DataTypes.DATE,
allowNull: true,
},
fidelityPoint: {
type: DataTypes.INTEGER,
defaultValue: 0,
},
group: {
type: DataTypes.INTEGER,
defaultValue: 0,
validate: {
isInt: true,
},
}
}, {
sequelize,
modelName: 'User',
tableName: 'Users',
timestamps: true,
updatedAt: false,
});
module.exports = sequelize.model('User');
console.log('User ->', User === sequelize.models.User);
controllers/user.js:
const validator = require('validator');
const bcrypt = require('bcrypt');
const { User } = require('../models/index');
exports.signup = (req, res, next) => {
let regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}/;
let firstName = req.body.firstName;
let lastName = req.body.lastName;
let email = req.body.email;
let phoneNumber = req.body.phoneNumber;
let password = req.body.password;
let birthday = req.body.birthday;
let fidelityPoint = req.body.fidelityPoint;
let group = req.body.group;
console.log('User ->', User);
if(email == null || phoneNumber == null || password == null || birthday == null) {
console.log('Creditentials ->', email, phoneNumber, password, birthday);
return res.status(401).json({ error: 'Champs vide' })
}
(async () => {
const user = {
firstName: firstName,
lastName: lastName,
email: email,
phoneNumber: phoneNumber,
password: password,
birthday: null,
fidelityPoint: fidelityPoint,
group: group,
}
await User.create(user)
.then(() => res.status(201).json({ message: 'Utilisateur créé avec succès !' }))
.catch(error => res.status(400).json({ message: 'Impossible de créer cet utilisateur', error }))
console.log('user instanceof User ->', user instanceof User);
})()
console.log('Signup User -> ', User);
}
If anyone can enlighten me that would be really nice of him 🙏
Alright, so I finally solved my problem. I had in fact this error which does not appear from my catch in the JSON but by adding the error in the console it sent me back:
Error: ConnectionManager.getConnection was called after the connection manager was closed!
Infact I closed the connection to the database before the work could be done so I removed the
finally {
db.close()
}
from my index.js and it works fine!
I have a mongo model like this:-
var mongoose = require('mongoose');
const itemsModel = new mongoose.Schema({
_id: {
type: String,
},
userName: {
type: String,
required: true
},
description: {
type: String,
required: false
},
itemId: {
type: String,
required: true,
unique: true
}
});
module.exports = mongoose.model("itemsModel", itemsModel);
and I am handling my backend route in a file called itemRoute.js like this:-
const express = require("express");
const router = express.Router();
const id = require('uuid');
const itemsModel = require("../src/model/itemsModel");
router.post('/add-item/', (req, res) => {
const { userName, description, itemId } = req.body;
itemsModel.findOne({
itemId: itemId,
userName: userName,
}, (error, prevData) => {
if(error){
return res.send({
success: false,
description: `Internal Server Error ${error}`
});
}
if (prevData.length > 0){
itemsModel.findOneAndUpdate(
{ _id: prevData[0]._id },
{ description: description },
(error, status) => {
if (error){
return res.json({
success: false,
description: `Internal Server Error ${error}`
});
} else {
return res.status(200).json({
success: true,
description: "Updated item successfully",
prevData: prevData,
status: status
});
}
}
);
}
const newModel = new itemsModel;
newModel._id = id.v4();
newModel.userName = userName;
newModel.itemId = itemId;
newModel.description = description;
newModel.save((error, user) => {
if(error){
return res.json({
success: false,
description: `Internal Server Error ${error}`
});
}
return res.status(200).json({
success: true,
description: "Added item to db",
user: user
});
});
});
});
router.get('/get-items/:itemId/', (req, res) => {
console.log(req.body);
const itemId = req.params.itemId;
return res.status(200).json({
success: true,
description: "Nicee",
id: itemId,
});
});
module.exports = router;```
I have the following in my index.js express file:-
app.use('/api', require('./routes/itemRoute'));
and I am calling from my frontend like this:-
handleAddItemButton = (event) => {
event.preventDefault();
const data = {
userName: this.props.userName,
description: this.state.description,
itemId: this.props.itemId,
}
fetch(`http://localhost:8000/api/add-item/`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(res => {
console.log(res);
})
.catch((err) => console.log(err));
};
My index.js file:-
/* jshint esversion:6 */
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const path = require('path');
const mongoose = require('mongoose');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(express.static('./build'));
app.use(express.static('./build/static'));
app.use('/api', require('./routes/auth'));
app.use('/api', require('./routes/items'));
app.use('/api', require('./routes/itemRoute'));
mongoose.set('useCreateIndex', true);
const port = 8000
mongoose.connect('mongodb://localhost:27017/item-app', {
useNewUrlParser: true
})
app.get('/*', (req, res) => {
res.sendFile(path.resolve('./build/index.html'))
})
app.listen(port, () => console.log(`server running at ${port}`));
When my frontend actually makes the request, I am thrown the following error:-
POST http://localhost:8000/api/add-item/ net::ERR_CONNECTION_REFUSED
I have looked through my code again and again but to no avail. Any and all help is sincerely appreciated. Please guide me through what Im doing wrong.
Edit 1:-
After #ewokx comment I ran mongod and got the following;-
Is this the issue? How to solve this?
MongoDB requires a data folder to store its files.
The default location for the MongoDB data directory is c:\data\db. So, create this folder it will solve your issue.
Hi so I seem to have successfully solved the problem. The problem wasn't with any of the things like db permissions, mongod, ports or something like that. I reset my index.js file to match the db name in the db connection.
Another thing I was doing wrong, I was passing a json stringified object as the request body. Removing that and on connecting proeprly to the db, the code started working nicely.
I have set up my react app on xxx.herokuapp.com, and my node app on yyy.herokuapp.com. Both are working, and I am the backend is able to send data to the front end. But when I want to send a cookie, no cookie is set. It works during local host, but not in production. I am also using cookieParser for cookies. Here is the code:
index.js:
app.use(
cors({
origin: [
"http://localhost:3000",
"https://xxx.herokuapp.com",
"https://yyy.herokuapp.com",
],
credentials: true,
})
);
auth.js:
export const signin = async (req, res, next) => {
try {
const user = await User.findOne({ username: req.body.username });
if (!user) return next(createError(404, "User does not exist!"));
const verifyPassword = bcrypt.compareSync(req.body.password, user.password);
if (!verifyPassword) return next(createError(400, "Invalid credentials!"));
const token = jwt.sign({ id: user._id }, process.env.JWT_KEY);
const { password, ...others } = user._doc;
res
.cookie("access_token", token, {
httpOnly: true,
})
.status(200)
.json(others);
} catch (error) {
next(error);
}
};
react:
const handleLogin = async (e) => {
e.preventDefault();
dispatch(loginStart);
try {
setOpen(true);
setAlert({ message: "Logged in.", severity: "success" });
const res = await axios.post(`${SERVER_URL}/auth/signin`, userForm, {
withCredentials: true,
});
dispatch(loginSuccess(res.data));
navigate("/");
// window.location.href = "/";
} catch (error) {
dispatch(loginFailure());
setOpen(true);
setAlert({
message: error.response.data.message,
severity: "error",
});
}
};
Had to put {sameSite: "none",
secure: true} in the res.cookie
I am trying to add a new member to a MailChimp list, but I keep getting the following error and can't understand why.
{
type: 'https://mailchimp.com/developer/marketing/docs/errors/',
title: 'Invalid Resource',
status: 400,
detail: "The resource submitted could not be validated. For field-specific details, see the 'errors' array.",
instance: '/* secret */',
errors: [
{
field: 'email_address',
message: 'This value should not be blank.'
}
]
}
Here is the code:
const express = require("express");
const bodyParser = require("body-parser");
const request = require("request");
const https = require("https");
const app = express();
app.use(express.static("public"));
app.use(bodyParser.urlencoded({
extended: true
}));
app.get("/", function(req, res) {
res.sendFile(__dirname + "/signup.html")
})
app.post("/", function(req, res) {
const firstName = req.body.fname;
const lastName = req.body.lname;
const email = req.body.mail;
console.log(firstName);
console.log(lastName);
console.log(email);
const data = {
members: [{
email_address: email,
status: "Subscribed",
merge_fields: {
FNAME: firstName,
LNAME: lastName
}
}]
};
const jsonData = JSON.stringify(data);
const url = "https://us5.api.mailchimp.com/3.0/lists/4e5319cda3/members"
const option = {
method: "post",
auth: "/* secret */"
}
const request = https.request(url, option, function(response) {
response.on(
"data",
function(data) {
console.log(JSON.parse(data));
})
})
request.write(jsonData);
request.end();
});
app.listen(3000, function() {
console.log("server is working in port 3000");
});
I think this endpoint from Mailchimp accept only one element not a list of members, try to send only one member
this is an example of the body from their documentation website
{"email_address":"","email_type":"","status":"subscribed","merge_fields":{},"interests":{},"language":"","vip":false,"location":{"latitude":0,"longitude":0},"marketing_permissions":[],"ip_signup":"","timestamp_signup":"","ip_opt":"","timestamp_opt":"","tags":[]}
In your case try to change your data const to :
const data = {
email_address: email,
status: "Subscribed",
merge_fields: {
FNAME: firstName,
LNAME: lastName
}
};
Remove /members form ... this
const url = "https://us5.api.mailchimp.com/3.0/lists/4e5319cda3/members"
I'm new to React. I'm having trouble understanding what is happening to my req.session.passport object that is created when a user logs in to the application. When logging into my application I get the following in my console:
axios.post(/login) response: login.component.js:39
Object { cookie: {…}, passport: {…} }
The problem comes when I go to another page. This appears on the console:
axios.get(/logged_in) response: user.component.js:37
this.state.session: user.component.js:38
Object { cookie: {…} }
Where did the passport object go? I need it to tell react who is logged in. I'm calling req.session in both axios paths so I expect to see the exact same result, but I don't. None of the topics similar enough to my situation has helped me figure out this problem.
onSubmit(e) function from login component:
onSubmit(e) {
e.preventDefault();
axios.post("http://localhost:4000/users/login", {
username: this.state.username,
password: this.state.password
}).then(res => {
console.log("axios.post(/login) response: ");
console.log(res.data);
if (res.status === 200) {
this.props.updateSession({
session: res.data
});
}
}).catch(err => {
console.log("Login error: ");
console.log(err);
});
this.props.history.push("/");
}
Route that the above function uses to authenticate a user:
router.post("/login", passport.authenticate("local"), (req, res) => {
console.log("Calling router.post(/login)...");
console.log("req.session: ", req.session);
res.status(200).json(req.session);
});
componentDidMount() function from the main user component that checks if a session is active:
componentDidMount() {
axios.get("http://localhost:4000/users/logged_in").then(res => {
this.setState({
session: res.data
});
console.log("axios.get(/logged_in) response: ");
console.log("this.state.session: ");
console.log(this.state.session);
}).catch(err => {
console.log(err);
})
}
Route that the above function uses. Very similar to the login route minus the authentication:
router.get("/logged_in", (req, res) => {
console.log("Calling router.get(/logged_in)...");
res.status(200).json(req.session);
});
localStrategy.js (Passport):
const User = require("../database/models/user.model"),
LocalStrategy = require('passport-local').Strategy;
const strategy = new LocalStrategy(
{
usernameField: "username" // not necessary, DEFAULT
},
function(username, password, done) {
User.findOne({ username: username }, (err, user) => {
if (err) {
return done(err)
}
if (!user) {
return done(null, false, { message: "Incorrect username" })
}
if (!user.checkPassword(password)) {
return done(null, false, { message: "Incorrect password" })
}
return done(null, user)
})
}
)
module.exports = strategy;
index.js (Passport):
const passport = require("passport"),
LocalStrategy = require("./localStrategy"),
User = require("../database/models/user.model");
passport.serializeUser((user, done) => {
console.log("*** serializeUser called, user: ");
console.log(user);
console.log('---------');
done(null, { _id: user._id });
})
passport.deserializeUser((id, done) => {
console.log("DeserializeUser called");
User.findOne(
{ _id: id },
"username",
(err, user) => {
console.log("*** Deserialize user, user:");
console.log(user);
console.log("--------------");
done(null, user);
}
)
})
passport.use(LocalStrategy);
module.exports = passport;
console.log result from serializeUser() above:
*** serializeUser called, user:
{ isAdmin: false,
orders: [],
createdAt: 2020-02-11T02:09:18.992Z,
_id: 5e420cdb...,
username: 'user',
password:
'$2a$1...',
__v: 0 }
server.js:
const express = require("express"),
app = express(),
bodyParser = require("body-parser"),
session = require("express-session"),
MongoStore = require('connect-mongo')(session),
cors = require("cors"),
PORT = 4000,
// Require routes
productRoutes = require("./routes/products"),
orderRoutes = require("./routes/orders"),
userRoutes = require("./routes/users"),
passport = require('./passport'),
dbConnection = require('./database');
app.use(bodyParser.json());
app.use(cors());
// Sessions
app.use(
session({
secret: "Birdhouses are cool.", // Secret can be any string
store: new MongoStore({ mongooseConnection: dbConnection }),
resave: false,
saveUninitialized: false
})
);
app.use(passport.initialize());
app.use(passport.session()); // calls serializeUser and deserializeUser
// Routes config
app.use("/products", productRoutes);
app.use("/orders", orderRoutes);
app.use("/users", userRoutes);
// Start server
app.listen(PORT, function() {
console.log("Server is running on Port: " + PORT);
});
User model:
const mongoose = require("mongoose"),
bcrypt = require("bcryptjs");
// Define user schema
let userSchema = new mongoose.Schema({
username: {
type: String
},
password: {
type: String
},
isAdmin: {
type: Boolean,
default: false
},
orders: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Order"
}],
createdAt: {
type: Date,
default: Date.now()
}
});
userSchema.methods = {
checkPassword: function(inputPassword) {
return bcrypt.compareSync(inputPassword, this.password);
},
hashPassword: plainTextPassword => {
return bcrypt.hashSync(plainTextPassword, 10);
}
}
userSchema.pre("save", function(next) {
if (!this.password) {
console.log("models/user.js =======NO PASSWORD PROVIDED=======")
next();
} else {
console.log("models/user.js hashPassword in pre save");
this.password = this.hashPassword(this.password);
next();
}
})
module.exports = mongoose.model("User", userSchema);