How to make an axios post to database? - javascript

I'm trying to make a login system which is part of my project with react, express, MySQL and Axios but I keep getting this error- Uncaught (in promise) Error: Request aborted
Server side:
const express = require("express");
const cors = require("cors");
const mysql = require("mysql");
const app = express();
app.use(express.json())
app.use(cors());
const db = mysql.createConnection({
host: "localhost",
user: "root",
password: "cool12345",
database: "users"
})
db.connect(err => {
if(err){
return err;
}
})
console.log(db)
app.post("/register", (req, res) => {
const username = req.body.username;
const password = req.body.password;
const email = req.body.email;
db.query("INSERT INTO teachers (name, email, password) VALUES (?,?)", [username, email, password], (error, result) => {
console.log(error)
})
db.query("INSERT INTO teachers (name, email, password) VALUES ('test', 'test2', 'test3')")
})
app.listen(4000, () => {
console.log("Listening on port 4000")
})
client side:
import React, { useState } from 'react'
import "../styling/SignUp.css";
import { useHistory } from "react-router-dom"
import Axios from "axios";
function SignUp() {
const [usernameReg, setUsernameReg] = useState("")
const [emailReg, setEmailReg] = useState("")
const [passwordReg, setPasswordReg] = useState("")
const register = () => {
Axios.post("https://localhost:4000/register", {username: usernameReg, email:emailReg, password: passwordReg}).then((response) => {
console.log(response)
})
}
the function in the client-side returns a form but there's too much code so I left it out of this question. The signup button has an onClick handler function which runs the register.

I doubt your localhost has an ssl certificate
try:
Axios.post("http://localhost:4000/register", {username: usernameReg, email:emailReg, password: passwordReg}).then((response) => {
console.log(response)
})
http instead of https
EDIT: I was too hasty to jump to a conclusion. What is that object you are passing to axios? I think it should be:
Axios.post("http://localhost:4000/register", {
data: {
username: usernameReg,
email:emailReg,
password: passwordReg
}
}).then((response) => {
console.log(response)
}).catch(err => console.log(err))
You can also catch the error. (So it won't be 'uncaught')

Axios.post("http://localhost:4000/register", headers: {
'Content-Type': 'application/json',
}, {
data: {
username: usernameReg,
email:emailReg,
password: passwordReg
}
}).then((response) => {
console.log(response)
}).catch(err => console.log(err))
Try setting a header called Content-Type/application/json when you are using a post request. application/json is used to transfer json data through requests.

Related

"Cannot set headers after they are sent to the client" for private routes after logging in JWT NodeJS

I am working on a backend for a Online mediconsult app and I came across this error in the JWT authentication. Since I am a newbie I dunno much about this topic. I have this 3 routes on my NodeJS /register, /login, /appointments. I was able to hit "/register" and "/login" perfectly fine. But when I copy the JWT token generated by "/login" route and paste it 'authorization' header it throws the problem.
node:internal/errors:484
ErrorCaptureStackTrace(err);
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at new NodeError (node:internal/errors:393:5)
at ServerResponse.setHeader (node:_http_outgoing:644:11)
at ServerResponse.header (C:\Users\krish\Desktop\mrcooper-task\server\node_modules\express\lib\response.js:794:10)
at ServerResponse.send (C:\Users\krish\Desktop\mrcooper-task\server\node_modules\express\lib\response.js:174:12)
at module.exports.login (C:\Users\krish\Desktop\mrcooper-task\server\controllers\authController.js:62:7) {
code: 'ERR_HTTP_HEADERS_SENT'
}
Node.js v18.12.0
A strange thing is, when I restart the server again with the same auth token, it works!.
Wonder why would it hit the above error before restarting ?
Code
index.js
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const app = express();
require('dotenv').config();
//External routes
const authRoutes = require("./routes/authRoutes");
const appointRoutes = require("./routes/appointRoutes");
// Middlewares
app.use(cors());
app.use(express.json());
//DB connection
const dbURI =
process.env.DB_URL;
mongoose
.connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true })
.then((result) =>
app.listen(8080, () =>
console.log("App sucessfully started on localhost port 8080")
)
)
.catch((err) => console.log(err));
//Internal routes
app.use(authRoutes);
app.use(appointRoutes);
appointRoutes.js
const { Router } = require("express");
const verify = require("./verifyToken")
const router = Router();
router.get("/appointments",verify, (req, res) => {
res.send({ message: "Appointment route" });
});
module.exports = router;
authRoutes.js
const { Router } = require("express");
const User = require("../models/User");
const bcrypt = require("bcryptjs");
const jwt = require("jsonwebtoken");
const { registerValidator, loginValidator } = require("../validation");
const router = Router();
router.post("/register", async (req, res) => {
//Validate data before creating a user
const { error } = registerValidator(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
//Check if email already exists
const emailExists = await User.findOne({ email: req.body.email });
if (emailExists) {
return res.status(400).send("Email already exists");
}
const { name, email, password, catogery, DOB } = req.body;
//Hash password
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
//console.log(hashedPassword);
try {
const user = await User.create({
name,
email,
password: hashedPassword,
catogery,
DOB,
});
res.status(201).json({ user: user._id });
} catch (err) {
//console.log(err);
res.status(400).send(err);
}
});
router.post("/login", async (req, res) => {
const { email, password } = req.body;
//Validate data before authenticating a user
const { error } = loginValidator(req.body);
if (error) {
return res.status(400).send(error.details[0].message);
}
//Check if email dosen't exists
const user = await User.findOne({ email: req.body.email });
if (!user) {
return res
.status(400)
.send("Email dosen't exists. Please register and try again");
}
//Passowrd is incorrect
const validPassword = await bcrypt.compare(password, user.password);
if (!validPassword) return res.status(400).send("Invalid Passowrd");
//Create and assign JWT token
const token = jwt.sign({_id: user._id}, process.env.TOKEN_SECRET)
res.header('auth-token', token).send(token);
//console.log(email, password);
res.send("Logged In!");
});
module.exports = router;
Here's what I did
I did few googles and searches on this error and found out that this error mainly throws out when we return multiple response per cycle. I checked the code below and I did'nt see multiple response coming from neither /login route nor /appointments route. Would there be any response leaks from if conditions accidentaly?
When I exit from nodemon and start again with the same take generated, now it can hit the /appointment. I wonder how it works ?
You get error when function like this
if(statement){
res.send(something)
}
res.send(something)
because code is continue after res.send() function
You must fix it to
if(statement){
return res.send(something)
}
return res.send(something)
and your res.send function in authController.js:62:7

POST http://localhost:5000/users/signin 500 (Internal Server Error) trying to make auth works

When I post the data for my Auth the console throws this error ** 500 (Internal Server Error) ** I think the problem is with my server, first check the database and the data is in the cluster
but the data does not work in my client. I know that this type of problem is often on the server. I've been searching for several hours and I can't figure it out.
This is the index
import express from 'express';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import cors from 'cors';
import postRoutes from './routes/posts.js';
import userRoutes from './routes/users.js';
const app = express();
app.use(bodyParser.json({ limit: '30mb', extended: true }))
app.use(bodyParser.urlencoded({ limit: '30mb', extended: true }))
app.use(cors());
app.use('/posts', postRoutes);
app.use('/users', userRoutes);
const CONNECTION_URL = '**THIS_IS_MY_MONGO_DB;
const PORT = process.env.PORT|| 5000;
mongoose.connect(CONNECTION_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => app.listen(PORT, () => console.log(`Server Running on Port: http://localhost:${PORT}`)))
.catch((error) => console.log(`${error} did not connect`));
mongoose.set('useFindAndModify', false);
The users.js route
import express from 'express';
import { signin, signup } from '../controllers/user.js';
const router = express.Router();
router.post('/signin', signin);
router.post('/signup', signup);
export default router;
The user controller
import bcrypt from "bcryptjs";
import jwt from "jsonwebtoken";
import User from "../models/user.js";
export const signin = async (req, res) => {
const { email, password} = req.body;
try {
const existingUser = await User.findOne({ email });
if(!existingUser) return res.status(404).json({ message: "El usuaruio no existe."});
const isPasswordCorrect = await bcrypt.compare(password, existingUser.password);
if(!isPasswordCorrect) return res.status(400).json({ message: "Credenciales invalidas."});
const token = jwt.sing({ email: existingUser.email, id: existingUser._id }, 'test', { expiresIn: "1h" });
res.status(200).json({ result: existingUser, token});
} catch (error) {
res.status(500).json({ message: 'Algo salio mal.' });
}
}
export const signup = async (req, res) => {
const { email, password, confirmPassword, firstName, lastName } = req.body;
try {
const existingUser = await User.findOne({ email });
if(existingUser) return res.status(400).json({ message: "El usuaruio ya existe."});
if(password !== confirmPassword) return res.status(400).json({ message: "Las contraseñas no coinciden."});
const hashedPassword = await bcrypt.hash(password, 12);
const result = await User.create({ email, password: hashedPassword, name: `${firstName} ${lastName}` })
const token = jwt.sing({ email: result.email, id: result._id }, 'test', { expiresIn: "1h" });
res.status(200).json({ result, token});
} catch (error) {
res.status(500).json({ message: 'Algo salio mal.' });
}
}
The index api
import axios from 'axios';
const API = axios.create({ baseURL: 'http://localhost:5000' })
export const fetchPosts = () => API.get('/posts');
export const createPost = (newPost) => API.post('/posts', newPost);
export const likePost = (id) => API.patch(`/posts/${id}/likePost`);
export const updatePost = (id, updatedPost) => API.patch(`/posts/${id}`, updatedPost);
export const deletePost = (id) => API.delete(`/posts/${id}`);
export const signIn = (formData) => API.post('/users/signin', formData);
export const signUp = (formData) => API.post('/users/signup', formData);
export const signup = async (req, res) => {
const { email, password, confirmPassword, firstName, lastName } = req.body;
try {
const existingUser = await User.findOne({ email });
if(existingUser) return res.status(400).json({ message: "El usuaruio ya existe."});
if(password !== confirmPassword) return res.status(400).json({ message: "Las contraseñas no coinciden."});
const hashedPassword = await bcrypt.hash(password, 12);
const result = await User.create({ email, password: hashedPassword, name: `${firstName} ${lastName}` })
// you have typo in next line
const token = jwt.sing({ email: result.email, id: result._id }, 'test', { expiresIn: "1h" });
// replace it by:
const token = jwt.sign({ email: result.email, id: result._id }, 'test', { expiresIn: "1h" });
res.status(200).json({ result, token});
} catch (error) {
res.status(500).json({ message: 'Algo salio mal.' });
}
}

Node.js throws TypeError: Cannot destructure property 'firstName' of 'req.body' as it is undefined, even though it works for an other post request

So I know there are tons of similar questions out there, and I've read most of them in the past few days. However I didn't find any solution to my problem. The app is about users can post memories(cards) etc... Point is, when I create a new card with POST request, there is no problem, but when I want to sign up a user then all hell breaks loose and throws this error:
(node:2732) UnhandledPromiseRejectionWarning: TypeError: Cannot destructure property 'firstName' of 'req.body' as it is undefined.
at signup (file:///E:/projects/personal/memories-app/backend/controllers/user.controller.js:39:13)
at Layer.handle [as handle_request] (E:\projects\personal\memories-app\backend\node_modules\express\lib\router\layer.js:95:5)
at next (E:\projects\personal\memories-app\backend\node_modules\express\lib\router\route.js:137:13)
I don't know that could be the problem, because other functions work so dunno really.
Here are the codes
server.js
import express from 'express';
import mongoose from 'mongoose';
import cors from 'cors';
import dotenv from 'dotenv';
import postRoutes from './routes/posts.routes.js';
import userRoutes from './routes/users.routes.js';
const app = express();
dotenv.config();
app.use(express.json({ extended: true }));
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use('/posts', postRoutes);
app.use('/users', userRoutes);
app.get('/', (req, res) => {
res.send('Hello to Memories API');
});
const PORT = process.env.PORT || 5000;
mongoose
.connect(process.env.CONNECTION_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() =>
app.listen(PORT, () => console.log(`Server running on port: ${PORT}`))
)
.catch((error) => console.log(error.message));
mongoose.set('useFindAndModify', false);
user.model.js
import mongoose from 'mongoose';
const userSchema = mongoose.Schema({
name: { type: String, required: true },
email: { type: String, required: true },
password: { type: String, required: true },
id: { type: String },
});
export default mongoose.model('User', userSchema);
the sign up method from user.controller.js
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import User from '../models/user.js';
export const signup = async (res, req) => {
const { firstName, lastName, email, password, confirmPassword } = req.body;
try {
const existingUser = await User.findOne({ email });
if (existingUser)
return res.status(400).json({ message: 'User already exists' });
if (password !== confirmPassword)
return res.status(400).json({ message: "Passwords don't match" });
const hashedPassword = await bcrypt.hash(password, 12);
const result = await User.create({
email,
password: hashedPassword,
name: `${firstName} ${lastName}`,
});
const token = jwt.sign(
{ email: result.email, id: result._id },
'test',
{
expiresIn: '1h',
}
);
res.status(200).json({ result, token });
} catch (error) {
res.status(500).json({ message: 'Something went wrong.' });
}
};
and just to see the createPost method (which works) from post.controller.js
import PostMessage from '../models/postMessage.js';
import mongoose from 'mongoose';
export const createPost = async (req, res) => {
const post = req.body;
console.log(post);
const newPost = new PostMessage(post);
try {
await newPost.save();
res.status(201).json(newPost);
} catch (error) {
res.status(409).json({ message: error.message });
}
};
And there is no problem with the front-end because when I simply console.log the req, I can see the body, but if I were to clg the req.body, then it is undefined. I've tried it with postman also, but no luck.
I would appreciate any insight on this! Thanks in advance!
You need to swap the order of res and req in the signup function, replace:
export const signup = async (res, req) => {
by:
export const signup = async (req, res) => {
Your User model does not have a firstName, lastName, and confirmPassword types use { name, email, password, } = req.body to sign up a new user.
In your project frontend use
name email, password, confirmPassword to register a use and email, password to log users in.

Error 401 Unauthorized in Browser and Postman ok

Good morning people
I am setting up the front-end for testing, In my application I use Passport, Token Jwt for authentication. At Postman, everything is ok! I can authenticate myself.
Now in the Browser, I log in it generates the token, however when trying to execute a route protected by the passport it returns me unauthorized
Follow my code. I'm a beginner, first post on the stackoverflow.
Routes.js
app.route('/rifas')
.all(app.config.passport.authenticate())
.post(app.api.rifas.saverifa)
Passport.js
const authSecret = process.env.authSecret
const passport = require('passport')
const passportJwt = require('passport-jwt')
const { Strategy, ExtractJwt } = passportJwt
module.exports = app => {
const options = {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKey: authSecret
}
const strategy = new Strategy(options,(payload, done) => {
app.db('users')
.where({id: payload.id})
.first()
.then( user => {
if(user) {
done(null, {id: user.id, email: user.email})
}
else {
done(null,false)
}
})
.catch(err => done(err,false))
})
passport.use(strategy)
return {
initialize: () => passport.initialize(),
authenticate: () => passport.authenticate('jwt', {session: false})
}
}
Archive api.js
import axios from 'axios'
const api = axios.create({
baseURL: 'localhost:3333',
})
export default api
Archive of front-end
async function handleLogin (e) {
e.preventDefault()
try {
const {data: token} = await axios.post('http://localhost:3333/signin', {
name: name,
email: email,
password: password
})
api.defaults.headers.Authorization = `Bearer ${token}`
window.location.href="http://localhost:3000/Header"
alert(`Logado com sucesso ${name}`)
}catch(e) {
alert('Erro no login')
}
}

front end react is not sending data to to mongoDB database

THE app is suppose to register the new user and send the new users info to the MongoDB, but when i attempt to register the user it throws an error of 500 internal error. the console says the error is in the user file, the terminal say this is the error, Proxy error: Could not proxy request /api/users from localhost:3000 to https://localhost:5000.
[1] See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (EPROTO).
I've already tried changing the proxy in the packet.json by giving it a different path and target but its not working. maybe i'm overlooking something. enter code here
import React, { useReducer } from 'react';
import axios from 'axios';
import AuthContext from './authContext';
import authReducer from './authReducer';
import {
REGISTER_SUCCESS,
REGISTER_FAIL,
USER_LOADED,
AUTH_ERROR,
LOGIN_SUCCESS,
LOGIN_FAIL,
LOGOUT,
CLEAR_ERRORS
} from '../types';
const AuthState = props => {
//initial state
const initialState = {
token: localStorage.getItem('token'),
isAuthenticated: null,
user: null,
loading: true,
error: null
};
const [ state, dispatch ] = useReducer(authReducer, initialState);
// load user
const loadUser = () => console.log('load user') ;
// register user
const register = async formData => {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
try {
const res = await axios.post('api/users', formData, config);
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
});
} catch (err){
dispatch({
type: REGISTER_FAIL,
payload: err.response.data.msg
});
}
}
// login user
const login = () => console.log('login') ;
//logut
const logout = () => console.log('logout') ;
// clear errors
const clearErrors = () => console.log('clearErrors') ;
return (
<AuthContext.Provider
value= {{
token: state.token,
isAuthenticated: state.isAuthenticated,
loading: state.loading,
user: state.user,
error: state.error,
register,
loadUser,
login,
logout,
clearErrors
}}>
{props.children}
</AuthContext.Provider>
);
};
export default AuthState;
//this is my server.js file with the routes
const express = require('express');
const connectDB = require('./config/db')
//connect MongoDB
connectDB();
const app = express();
//init middleware
app.use(express.json({extended: false}));
app.get('/', (req, res) => res.json({ msg: 'hello welcome'})
);
//define routes
app.use('/api/users', require('./routes/users'));
app.use('/api/auth', require('./routes/auth'));
app.use('/api/contacts', require('./routes/contacts'))
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => console.log(`server is working on ${PORT}`))
// this is mongoDB code
const mongoose = require('mongoose');
const config = require('config');
const db = config.get('mongoURI');
const connectDB = async () =>{
try{ await
mongoose.connect(db, {
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false
});
console.log('mongo connected..')
} catch (err){
console.log(err.message);
process.exit(1)
}
};
module.exports = connectDB;
// this the users file where the console is throwing the 500 internal error.
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');
const config = require('config');
const { check, validationResult } = require('express-validator');
const User = require('../models/User')
// This route Post request to api/users,
// description register a user,
// access to public to register an become a user
router.post('/', [
check('name', 'Name is require').not().isEmpty(),
check('email', 'please include email').isEmail(),
check('password', 'enter a password with atleast 6 characters'
).isLength({min: 6})
],
async (req, res) =>{
const errors = validationResult(req);
if(!errors.isEmpty()){
return res.status(400).json({ errors: errors.array()});
}
const { name, email, password } = req.body;
try{
let user = await User.findOne({email});
if(user){
return res.status(400).json({msg: 'user already exist'})
}
user = new User({
name,
email,
password
});
const salt = await bcrypt.genSalt(10);
user.password = await bcrypt.hash(password, salt);
await user.save();
// object to send in the token
const payload = {
user: {
id: user.id
}
}
jwt.sign(payload, config.get('jwtSecret'), {
expiresIn: 36000
}, (err, token) => {
if(err) throw err;
res.json({token});
});
} catch (err){
console.log(err.message);
res.status(500).send('server error')
}
});
module.exports = router;
I figure out the problem!!!
I had an unexpected token in my users file that simple colon was interfering with the code

Categories

Resources