Register route 404 not found - javascript

I am building a register page and when I submit the I am getting a 404 not found. I am using react and express and I think the front end is good. I am missing some back end or have the wrong url for my post request: axios.post('http://localhost:3000/auth'. Would appreciate some advice if anyone can see what I have wrong.
const handleSubmit = event => {
event.preventDefault();
const user = {
username: username,
password: password,
}
axios.post('http://localhost:5000/', { user })
.then(res=>{
console.log(res);
console.log(res.data);
})
}
This is the registerPost function for my route.
export const registerPost = async (req, res) => {
const {username, password} = req.body;
const newUser = new User({username, password});
try {
await newUser.save();
console.log(newUser);
res.status(201).json(newUser);
} catch (error) {
res.status(409).json({ message: error.message });
}
}
These are the routes.
import express from 'express';
import { getPosts } from '../controllers/posts.js'
import { createPost, updatePost, deletePost, registerPost } from '../controllers/posts.js'
const router = express.Router();
router.get('/', getPosts);
router.post('/', createPost);
router.patch('/:id', updatePost);
router.delete('/:id', deletePost);
router.post('/auth', registerPost);
export default router;

You're getting a 404 error, which means the url you're trying to reach does not exist. In the React app, you're sending the request at http://localhost:5000/, but in the Express app, you've defined the register route as /auth.
Updating the url in the React app to http://localhost:5000/auth should fix this.

As far as I can see you're passing the following Object from the Frontend:
{ user: { username, password } }
but in the backend you're not looking for the user property, but directly for the username and password.
const {username, password} = req.body
// =>
const { user } = req.body

Related

request to login to a node server, using react

Here is the situation:
I have a database which contains a user and password registered.
My assignment, for now, is to create a login form, and login with a registered uname and pw.
Uname and pw are registered in the server/database already.
ps: I did not create the server nor database.
Node server code
import express from 'express';
import cors from 'cors';
import http from 'http';
import { Sequelize } from 'sequelize';
import { Data } from './database';
import { router } from './routes/Router';
import { initialData } from './database/someData';
const closeServer = async (
server: http.Server,
sequelize: Sequelize,
signal?: string
) => {
server.close();
await sequelize.close();
process.exit();
};
const runServer = async (): Promise<void> => {
const PORT = process.env.PORT || 8082;
const app = express();
const sequelize = Data.init();
app.use(
cors({
credentials: true,
origin: 'http://localhost:3000',
})
);
app.use('/api', router);
const server = app.listen(PORT, () => {
console.log(`Starting server at ${PORT}`);
});
try {
await sequelize.authenticate();
await sequelize.sync({
force: process.env.SERVER === 'reset',
});
if (process.env.SERVER === 'reset') await initialData();
} catch (e) {
closeServer(server, sequelize);
throw e;
}
};
runServer()
.then(() => {
console.log('Run successfully');
})
.catch((ex: Error) => {
console.log('Unable to run:', ex);
});
I need help on what is that I have to do.
When I input username and pw, on the form, what are the methods to use for sending the info?
And then, when the info reaches the server, i think the username and pw need to be validated with jwt, and then check if the user and pw exists. how do i do that?
What i have understood so far is that i gotta use axios to send info to server, but thats it.
Do i need to use jwt for the login?
What is the normal flow for this kind of mechanism?
I am using react as a framework.
So there are quite few steps here.
First you have to create endpoint on your backend server for issuing jwt tokens. Jwt tokens can be used as a pass for user to login. So in your router you would add something like this:
router.post('/login', (req, res)=> {
const username = req.body.username
const password = req.body.password
// Then you make db call to verify username and password are correct.
if Credentials are valid, you would issue jwt token
jwt.sign({
// here you can save extra information of user. Also remember this information must be public since anyone can see it. Do not put user password here
email: 'email',
userId: 'id',
}, "secret")
})
After this, you need some kind of middleware on backend, so that on each user request, you check and verify this jwt token which is sent from react application. For example you could write isAuth middleware:
const jwt =require("jsonwebtoken");
export const isAuth= (req, res, next) => {
try {
// here we attach request in auth header, with Bearer "jwt token" format. So we extract jwt token and verify it
const authHeader = req.get("Authorization");
if (!authHeader) {
return res.status(401).json({ message: "no token" });
}
const token = authHeader.split(" ")[1];
let decodedToken;
decodedToken = jwt.verify(token, "secret");
if (!decodedToken) {
return res.status(401).json({ message: "Wrong token" });
}
req.userId = decodedToken.userId;
next();
} catch (err) {
console.error(err);
return res.status(401).json({ message: err });
}
};
Now you would be able to have backend endpoints like this:
// This is how you would require login on some routes
router.post("/getMyPrivateInfo", isAuth, QueryPrivatInfo)
Now on React side, you would make request for login like this:
axios.post("/login", {
username: '1',
password: "2"
})
This would return jwt token, now you would save this token in local storage.
After its saved in local storage and you make request with axios for private info you would do following
axios.post("/getMyPrivateInfo", {any request body info neeeded}, {
headers: {
Authorization: "Bearer jwtTokenFromLocalStorage"
}
})
This is how whole flow will work, hope it makes sense

"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

Receiving 404 Error from Axios post request to MongoDB

I am working on a MERN stack project for a proof-of-concept and am creating a wall where I can add posts from a form. The form accepts name, tags, title, and a message along with an image. Upon clicking submit, Axios gives me a 404 error in the console.
For example, trying to POST this data (using a mongoose schema):
{creator: 'asdfasddd', title: 'asdfasd', message: 'asdffdd', tags: 'dddd', selectedFile: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA0gA…AAAAAAAAAAAAAAAAAYI+9AisfoxArdwtiAAAAAElFTkSuQmCC'}
And I receive this error message:
{message: 'Request failed with status code 404', name: 'AxiosError', code:
'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
This is the AxiosError expanded only once, I can expand the error further if that would help, I've looked through it an found nothing in particular that seems helpful.
[
If somebody could tell me why I am getting this error besides the fact that I am timing out and what would cause me to that would be helpful. One note to help is that I receive some interaction to my DB just no data (of course). My POST functions are here if that helps as well, but I don't believe that is wrong either. If I need to post my the code to my component itself let me know.
import * as api from '../api';
// Action Creators
export const getPosts = () => async (dispatch) => {
try {
const { data } = await api.fetchPosts();
dispatch( {type: 'FETCH_ALL', payload: data });
} catch (error) {
console.log(error.message);
}
}
export const createPost = (post) => async (dispatch) => {
try {
const {data } = await api.createPost(post);
dispatch({type: 'CREATE', payload: data});
} catch (error) {
console.log(post);
console.log(error.toString());
console.log(error);
}
}
Code for POSTS for the back end in my controllers folder.
import PostMessage from '../models/postMessage.js';
export const getPosts = async (req, res) => {
try {
const postMessages = await PostMessage.find();
console.log(postMessages);
res.status(200).json(postMessages);
} catch (error) {
res.status(404).json({ message: error.message});
}
}
export const createPost = async (req, res) => {
const post = req.body;
const newPost = new PostMessage(post);
try {
await newPost.save();
res.status(201).json(newPost);
} catch (error) {
res.status(409).json({ message:error.message});
}
}
Within api folder:
import axios from 'axios';
const url = 'http://localhost:5000/posts';
//const port = process.env.PORT;
//const url = 'http://localhost:3000/posts';
export const fetchPosts = () => axios.get(url);
export const createPost = (newPost) => axios.post(url, newPost);
How the data is routed server-side:
import express from 'express';
import { getPosts, createPost } from '../controllers/posts.js';
const router = express.Router();
//http://localhost:5000/posts
router.get('/', getPosts);
router.get('/', createPost);
export default router;
In your router file, you are missing the POST method
router.post('/', createPost);
In your main file, it should be
app.use("/posts", postRouter)

I am receiving a "User.findOne is not a function" error message despite this same model working in another file. Similar question answers didn't work

First time posting on here, FYI.
Below is my "User" model in its own file. I create the schema and assign it. When I go to use this model in my authRoutes file it works fine just as you'd imagine. But when I use an identical import in one of my screen files I receive the "User.findOne is not a function" error message (linked below).
I am using this method to find a user in the database in order to access it's attributes. I have tried using the module.exports way of exporting the model and also trying to use require() as the import statement...neither has fixed my issue...been stuck on this for a while some insight would be great! (Hopefully this was clear, let me know)
"User.findOne is not a function..."
models/User.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: true
},
password: {
type: String,
required: true
},
balance: {
type: Number,
default: 100,
}
});
mongoose.model('userSchema', userSchema);
routes/authRoutes.js (Works here)
const mongoose = require('mongoose');
const User = mongoose.model('userSchema');
const express = require('express');
const router = express.Router();
//const User = require('../models/User');
const jwt = require('jsonwebtoken');
router.post('/signup', async (req, res) => {
const {email, password} = req.body;
try {
const user = new User({email, password});
await user.save();
const token = jwt.sign({ userId: user._id}, 'SOME_SECRET_KEY');
res.send({token});
} catch (err) {
return res.status(422).send(err.message);
}
});
router.post("/signin", async (req, res) => {
const {email, password} = req.body;
if (!email || !password) {
return res.status(422).send({error: "Must provide email and password."});
}
const user = await User.findOne({ email });
if (!user) {
return res.status(422).send({ error: "Invalid email or password"});
}
try {
//await user.comparePassword(password);
const token = jwt.sign({userId: user._id}, "SOME_SECRET_KEY");
res.send({token, email});
} catch (err) {
return res.status(422).send({ error: "Invalid email or password"});
}
})
screens/SomeScreen.js (Does NOT work here, error)
import React, {useContext, useState} from 'react'
import {View, StyleSheet, Text, ScrollView, TextInput, Button} from 'react-native';
//import { LinearGradient } from 'expo-linear-gradient';
import colors from '../../constants/colors';
import RecieverCard from '../../components/RecieverCard';
import HistoryCard from '../../components/HistoryCard';
import {Provider, Context} from "../context/AuthContext";
import AsyncStorage from "#react-native-async-storage/async-storage";
const mongoose = require('mongoose');
const User = mongoose.model('userSchema');
const getUserBalance = async (userEmail) => {
let user;
try {
user = await User.findOne(userEmail);
} catch(err) {
console.log(err);
}
return user;
};
require is not a React api, and so it will not work in your frontend.
You should use that in your node.js backend.
Regardless, why would you use mongoose & models in your frontend? I suggest you make an endpoint / controller responsible of getting the user balance in your backend, and then simply send a request to your backend and await for the response data.

How do I query with url parameter?

I am new to Node.js and trying to check if an e-mail is already taken by sending the email as a url parameter from iOS app. It is not working, not sure what I am doing wrong.
I am unable to console.log the email parameter in VSCode sent from the front-end, it DOES print in XCODE ( http://localhost:3000/api/user/email/test#gmail.com ) and I know the backend is getting the GET request.
My router code is:
const express = require(`express`)
const router = new express.Router()
const User = require(`../models/user-model`) // import User model
router.get(`/api/user/email/:email`, async (req, res) => {
console.log(req.params) // does NOT print email: test#gmail.com
try {
const user = await User.findOne(req.params.email)
if (user) {
console.log(user._id)
res.send({ available: false })
} else {
res.send({available: true})
}
} catch {
res.status(404).send()
}
})
Thank you!
const express = require(`express`)
const app = new express();
app.get(`/api/user/email/:email`, async (req, res) => {
console.log(req.params) // does NOT print email: test#gmail.com
try {
// const user = await User.findOne(req.params.email)
const user = {_id:123};
if (user) {
console.log(user._id)
res.send({ available: false })
} else {
res.send({available: true})
}
} catch {
res.status(404).send()
}
})
app.listen(3000,function(){
console.log("running");
})
Editing this.. I dont have enough points to comment.. your route seems to be fine, maybe you are not telling your application to use this route, somewhere before starting your application you should have something like:
this.app = new express();
...
this.app.use('/api', MailRouter); //<=== Adding your required mail route
...
I use to split url one parte here (/api) and the other one in the router (/user/email/:email). I'm not sure how to do it by adding it fully to the router (Maybe '/' maybe '')

Categories

Resources