Passing query parameter in nodejs but route is giving error - node.js

I want to pass the query parameter in the route. I used authentication middleware.
I want to delete a task based on that task id. Later I want to pass auth into delete by id route and allow the user to delete a task by authentication, but when I pass the query parameter the endpoint fails. If no query parameter is passed everything works fine.
task.js
const express = require('express')
require('../mongoose')
const Task = require('../model/task_model')
const auth = require('../middleware/user_middleware')
const router = new express.Router()
router.delete('/tasks/del/:id', async (req, res) => {
try {
const task = await Task.findByIdAndDelete(req.params.id)
if (!task) {
res.status(404).send()
}
res.send(task)
} catch (e) {
res.status(500).send()
}
})
module.exports = router
index.js
const express = require('express')
const UserRouter = require('./router/user')
const TaskRouter = require('./router/task')
const app = express()
const port = process.env.PORT || 3000
app.use(express.json())
app.use(UserRouter)
app.use(TaskRouter)
app.listen(port,()=>{
console.log('Server listening on port: ' + port)
})
middleware.js
const jwt = require("jsonwebtoken")
const User = require("../model/user_model")
const auth = async function(req,res,next){
try {
const token = (req.headers.authorization).split(' ')[1]
const decoded_token = jwt.verify(token,'ankan123')
const user = await User.findOne({_id:decoded_token._id,"tokens.token":token})
if (!user){
throw new Error()
}
req.user = user
req.token = token
next()
} catch(e){
res.status(400).send("PLease Authenticate")
}
}
module.exports = auth
task_model.js
const mongoose = require('mongoose')
const TaskSchema = new mongoose.Schema({
task: {
type: String,
required:true,
},
completed:{
type: Boolean
},
creator:{
type: mongoose.Schema.Types.ObjectId,
required:true
}
})
const tasks = mongoose.model('Task', TaskSchema)
module.exports = tasks
user.js
const express = require('express')
require('../mongoose')
const User = require('../model/user_model')
const auth = require('../middleware/user_middleware')
const router = new express.Router()
router.post('/users/login', async (req, res) => {
try {
const user = await User.matchCred(req.body.mobileNo, req.body.password)
const token = await user.generateToken(user._id)
return res.status(200).send({
user,
token
})
} catch (e) {
res.status(400).send()
}
})
module.exports = router;
I am getting route containing /tasks/del/:id does not exist when using postman to send delete requests.

The issue is simple you are passing it as query parameters, but it is path parameters. You can run like this in the postman:
{url}/tasks/del/'yourID'
When you pass id as query parameters, it won't be able to match the path and hence you are receiving an error Can't Delete. I would say you should understand diff b/w them and you can check this link.

Related

Mongoose: Operation `schema.findOne()` buffering timed out after 10000ms

I have a REST API made with Node.js and I use Mongoose to connect with MongoDB. Whenever I try to interact with the DB using Mongoose, I get the timeout error.
I have made sure that the DB is running and accepts connections from my IP. Using the same connection method in other projects works for some reason.
I am using mobile hotspot connection. Could that be an issue?
server.js
const express = require('express');
const app = express();
const cors = require('cors');
const userRoutes = require('../Backend/routes/userRoutes')
const taskRoutes = require('../Backend/routes/taskRoutes')
const mongoose = require('mongoose');
require('dotenv').config()
mongoose.connect(process.env.DB_CONNECTION);
app.use(cors());
app.use(express.json());
app.use(userRoutes)
app.use(taskRoutes)
app.listen(process.env.PORT || 3000 , () => {
console.log("API is now running.")
});
userRoutes.js
const userController = require('../controllers/userController')
const express = require('express');
const router = express.Router();
router.get('/users/currentUser', userController.getCurrentUserData)
router.get('/users/:userId', userController.getUserData)
router.post('/register', userController.register);
router.post('/login', userController.login);
module.exports = router;
Method in userController that causes the error (the error is caused by no matter which method I call out)
exports.login = async (req, res) => {
if (!req.body.username || !req.body.password) {
return res.status(400).send("Missing one or all required request body fields: username, password");
}
let existingUser;
try {
existingUser = await userSchema.findOne({ username: req.body.username });
} catch(err) {
return res.status(500).send("Internal server error."); //Error comes from here
}
if (!existingUser) {
return res.status(404).send('User not found');
}
const isPasswordCorrect = await bcrypt.compare(req.body.password, existingUser.password);
if (!isPasswordCorrect) {
return res.status(401).send('Invalid credentials');
}
let token;
try {
token = jwt.sign(
{ userId: existingUser._id, username: existingUser.username, tasks: existingUser.tasks},
process.env.SECRET,
{ expiresIn: "1h" }
);
} catch (err) {
console.log(err);
return res.status(500).send("Couldn't create JWT.")
}
return res.status(200).json({ token: token });
}
User model
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const userSchema = new mongoose.Schema({
username:{
type: String,
unique: true
},
password:{
type: String
},
tasks:{
type:[mongoose.Types.ObjectId]
}
})
userSchema.pre('save', async function(next) {
const salt = await bcrypt.genSalt();
this.password = await bcrypt.hash(this.password, salt);
next();
});
module.exports = mongoose.model('user',userSchema);
.env
DB_CONNECTION="mongodb://localhost:27017/test"
SECRET='test'

I receive no response from the requests i send in NodeJS API it just keeps loading

my code was perfectly working a couple of days ago and it suddenly stopped working it's connected to the mongodb cluster but i fail to receive response from the database everytime i send a request it's i tried reinstalling node reinstalling mongoose updating all packages but nothing seemed to work
keeps loading forever
and no response when i cancel it
here's the server.js code :
const express = require('express');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const mongoose = require('mongoose');
const cors = require('cors')
require('dotenv/config');
const authJwt = require('./helpers/jwt')
const errorHandler = require('./helpers/error-handler')
const api = process.env.URL;
mongoose.connect(process.env.DATABASE,
{
useNewUrlParser:true,
useUnifiedTopology:true
})
.then(()=>{
console.log('connected to database')
})
.catch((err)=>{
console.log(err)
})
//variables
const app = express();
const port = 9090
//middleware calls
app.use(bodyParser.json());
app.use(morgan('tiny'));
app.use(express.Router())
//app.use('')
app.use(cors());
app.options('*',cors())
app.use(errorHandler)
app.use(authJwt)
const categoriesRouter = require('./routers/categories')
const productsRouter = require('./routers/products')
const ordersRouter = require('./routers/orders')
const usersRouter = require('./routers/users')
//Routers
app.use(`${api}/categories`,categoriesRouter)
app.use(`${api}/products`,productsRouter)
app.use(`${api}/users`,usersRouter)
app.listen(port,(req,res)=>
{
console.log('server is running in port '+ port )
})
here's one of the routers code :
const {Category} = require('../models/category')
const express = require('express');
const router = express.Router();
router.get('/',async(req,res)=>{
const categoryList = await Category.find();
if(!categoryList)
{
res.status(500).json({success:false})
}
res.status(200).send(categoryList);
})
router.get('/:id',async(req,res)=>{
const category = await Category.findById(req.params.id)
if(!category)
{
res.status(500).json({message:'The category with the given ID'})
}
res.status(200).send(category)
})
router.post('/',async(req,res)=>{
let category = new Category({
name:req.body.name,
icon:req.body.icon,
color:req.body.color
})
category = await category.save();
if(!category)
return res.status(404).send('the fag category cannot be created')
res.send(category)
})
router.delete('/:id', (req,res)=>{
Category.findByIdAndRemove(req.params.id).then(category=>{
if(category)
{
return res.status(200).json({success:true,message:'the category is deleted'})
}
else
{
return res.status(404).json({success:false,message:'the category is not found'})
}
}).catch(err=>{
return res.status(400).json({success:false , error: err})
})
})
router.put('/:id',async (req,res)=>{
const category = await Category.findByIdAndUpdate(
req.params.id,
{
name:req.body.name,
icon:req.body.icon,
color:req.body.color
},
//i want to return the new updated data
{ new:true }
)
if(!category)
{
return res.status(400).send('The category cannot be created!');
}
res.send(category);
})
module.exports = router;
just to let you know it was working a couple of days ago and now it just suddenly stopped working if there's anything i can do or if you've faced the same problem before please reach out
Make sure to send a proper response on the api side of code.
In the case that u are using the express framework, it could look something like this:
router.get('/', (req, res) => {
res.status(200).json({
your: data
})
})

Lose access to part of my database when I switch to a different server location

Context: I am using mongoDB to store my data on my first API, it's made in node.js. I'm currently working on creating a login system. When I post the account to my API I set the _id value to the email address so to access it I can just do api.com/logins/email. Whenever I do that I get this in return
{"_id":"email","password":"password","__v":0}
However when I switch the server location (from my server to my laptop for dev testing) I can no longer access the logins by _id. I can still access the entire collection, but when I attempt to call specifically by the _id I get Cannot GET /logins/email This also happens if after the fact I reopen the API server on my personal server
In order to fix this I have to delete all the collections in that area and re add one from the app. Once I do this everything works again however when my app goes live I would want to have this fixed because otherwise everyone would need to remake their accounts when I do work on the API
With this being my first API I'm kind of at a loss for what's happening and why it is, any help would be appreciated
Relevant code from sign in page (yes I am aware that base64 isn't encrypting I just haven't change it yet)
const login = async () =>{
encrypted = (await encrypt())
console.log(email.toUpperCase())
var mail = email.toUpperCase()
var test = await fetchSingleData(url,mail)
console.log(test)
if (test==null){
console.log("Invalid email")
return
}
console.log(test.password == encrypted)
if (encrypted == test.password){
console.log("I'm in")
setEmail("")
setPassword("")
navigation.navigate("Sheet")
}
else console.log("Invalid Password")
}
const encrypt = async () =>{
var enc = Base64.encode(password)
console.log(enc)
return enc
}
Mongoose connection code
const express = require('express')
const app = express()
const mongoose = require('mongoose')
require('dotenv/config')
const bodyParser = require('body-parser')
const MONGOBD_URL = process.env.DB_CONNECTION
var https = require("https")
var fs = require("fs");
var path = require("path")
app.use(bodyParser.json())
//Import routes
const postsRoute = require('./routes/posts')
const loginRoute = require("./routes/logins")
app.use('/posts', postsRoute)
app.use('/logins', loginRoute)
//ROUTES
app.get('/',(req,res)=>{
res.send("We are on home")
})
//LISTENER
app.listen(19010)
//Connect to DB
mongoose.connect(MONGOBD_URL,{useNewUrlParser:
true},()=>{console.log("connected to DB")})
module.exports = app;```
Routing
const express = require('express')
const router = express.Router();
const Login = require("../Models/Login")
//GET ALL ACCOUNTS
router.get('/',async (req,res)=>{
console.log("req")
try{
const logins = await Login.find()
res.json(logins)
}catch(err)
{
res.json({message: err})
}
})
// CREATES ACCOUNT
router.post('/', async (req,res) => {
const login = new Login({
_id: req.body._id,
password: req.body.password
})
//SPECIFIC ACCOUNT
router.get('/:postID', async (req,res) =>{
try{
const login = await Login.findById(req.params.postID)
res.json(login)
}
catch(err){res.json({message:err})}
})
const savedLogin = await login.save()
try{
res.json(savedLogin)
}catch(err){
res.json({message: err})
}
})
//DELETE ACCOUNT
router.delete('/:postID', async (req,res) => {
try{
const remove = await Post.remove({_id:req.params.postID})
res.json(remove)
}
catch(err){res.json({message:err})}
})
module.exports = router
Data example in database
okay so let us get to this...I'm not too sure what the cause of this issue is, but let us go through your code and try to isolate it. So we will begin by neatening things up a little.
starting with your login code:
const login = async () => {
encrypted = (await encrypt())
var mail = email.toUpperCase()
var test = await fetchSingleData(URL, mail)
// [TIP]: this is sufficient to achieve the same logic.
if (!test) {
return
}
if (encrypted == test.password) {
setEmail("")
setPassword("")
navigation.navigate("Sheet")
}
else
console.log("Invalid Password")
}
//...
const encrypt = async () => {
return Base64.encode(password)
}
Okay let check out your route configuration.
// [TIP]: import everything first
const express = require('express')
const mongoose = require('mongoose')
const bodyParser = require('body-parser')
// [TIP]: const on everything that wont change
const https = require("https")
const fs = require("fs");
const path = require("path")
require('dotenv/config')
const MONGOBD_URL = process.env.DB_CONNECTION
const app = express()
app.use(bodyParser.json())
//Connect to DB
// [FIX]: Connect to the database first before referencing it in your routes
// [NOTE]: Express is a static server and cannot change after configuring
// the routes that you have.
mongoose.connect(MONGOBD_URL,
{ useNewUrlParser: true },
() => console.log("connected to DB"))
//Import routes
const postsRoute = require('./routes/posts')
const loginRoute = require("./routes/logins")
// I do not know what goes on here
app.use('/posts', postsRoute)
// or here, but suspect your issue lies here.
app.use('/logins', loginRoute)
//ROUTES
app.get('/', (req, res)=>{
res.send("We are on home")
});
//LISTENER
app.listen(19010, () => console.log('server listening on port 19010'));
module.exports = app;
Im still not sure what the problem could be with this code, my suspicion is still with your database connection.
So in the end the issue was my brackets. They were set up in a way that so that the singular get was only created when I did a POST

req.params.userId not found ( path set to /:userId) Node.js

I want to get an user by his userId parameter but it doesn't work. The app connects to the database(Atlas), I can create users, retrieve them all in bulk but I can't retrieve them with a specific parameter ( in this case UserId), producing a not found error message.
UserRoutes.js
const express = require('express');
const UserModel = require('../models/UserModel');
const app = express();
app.get('/getusersById/:userId', async (req, res) => {
const user = await UserModel.find(req.params.userId);
try {
res.send(user);
} catch (err) {
res.status(500).send(err);
}
});
UserModel.js
const mongoose = require('mongoose');
// Define Schema
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true,
trim: true,
},
age: {
type:Number,
required:true
},
userId: {
type:String,
required:true
},
});
//
const User = mongoose.model('user', UserSchema);
module.exports = User;
Server.js
// Open connection to test database
const express = require('express');
const mongoose = require('mongoose');
const UserRouter = require('./routes/UserRoutes.js');
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const uri = "mongodb+srv://XXXXXXXXXXX#XXXXXXXeXXXX.gcp.mongodb.net/dbusers?retryWrites=true&w=majority";
mongoose.connect(uri,{
userNewUrlParser: true,
useUnifiedTopology: true
});
// Notify if connection was succesful
var db = mongoose.connection;
db.on ('error', console.error.bind(console, 'connection error'));
db.once('open', function() {
console.log("Connection Succesful");
});
db.on('close', () => {
db.removeAllListeners();
});
// Router & Port
app.use(UserRouter);
app.listen(3000,
() => {console.log('Server is running...')});
And this is the postman request:
Postman get userId
Your request is wrong. You defined your path as:
app.get('/getusersById/:userId', /* callback */)
So the request URL should be:
/getusersById/3
and not
/getusersById/?userId=3
'/getusersById/:userId'
What you are doing here is parameters of your request, which is userId
the correct usage of this api is /getusersById/3
app.get('/getusersById/:usersId', async (req, res) => {
const user = await UserModel.find(req.params.usersId );
However it seems you want to use ?usersId=3 for query the user id
You need to use req.query.usersId
app.get('/getusersById', async (req, res) => {
const user = await UserModel.find(req.query.usersId );
You can find examples of query usage : https://coderrocketfuel.com/article/handle-get-request-query-string-parameters-in-express-js
I think you are new to API development. From the image that I can see that you are sending userId as a query parameter. But in code, you are doing req.parms.userId which is used for path params. In your code you defined route for path parameter so the request should be like this:
/getusersById/3
And to be handled as below
app.get('/getusersById/:userId', async (req, res) => {
const user = await UserModel.find(req.params.userId );
However, If you want to pass userId in query parameter then do this:
app.get('/getusersById', ...)
request can be made like this:
/getusersById/?userId=3
and query parameter will be accessible as below:
app.get('/getusersById', async (req, res) => {
const user = await UserModel.find(req.query.userId );
Read this: Query vs Path params

Route declared properly but still getting a Could not get any response error

I have making an API using express and node.
Here is my app.js
const express = require('express');
const bodyParser = require('body-parser');
const dotenv = require('dotenv');
// setup dotenv to read environment variables
dotenv.config()
// Load Environment Varibles
const env = require('./utils/env');
// INIT MONGODB CONNECTION
require('./mongoose');
// create a new express application
const app = express();
// setup bodyparser middleware to read request body in requests
// we're only reading JSON inputs
app.use(bodyParser.json());
// Listen to API routes
const apiRoutes = require('./routes')
app.use('/api', apiRoutes);
// Start listening to requests
app.listen(env.PORT, () => {
console.log(`Server started on PORT ${env.PORT}`);
});
And here is the API routes that are being imported
const express = require('express');
const apiController = require('./apiController');
const apiValidator = require('./apiValidator');
const router = express.Router();
router.post('/login', apiValidator.loginUserValidator, apiController.loginUserController);
router.get('/rand', (req, res) => {
res.send('Some randon text');
});
module.exports = router;
Here is the middleware
const {
failureResponse
} = require('./../utils/response');
const errorcodes = require('./../utils/errorcodes');
const loginUserValidator = (req, res, next) => {
const user = req.body;
if (!user.username) {
return res.status(400).json(failureResponse(errorcodes.ERROR_INVALID_BODY_PARAMETER, "Invalid username"));
}
if (!user.password) {
return res.status(400).json(failureResponse(errorcodes.ERROR_INVALID_BODY_PARAMETER, "Invalid password"));
}
if (user.authTokens) {
delete user.authTokens;
}
next();
};
module.exports = {
loginUserValidator
};
Here is the controller
const User = require('./../models/user');
const {
successResponse,
failureResponse
} = require('./../utils/response');
const errorcodes = require('./../utils/errorcodes');
const loginUserController = async (req, res) => {
try {
const user = req.body;
// find if the user already exists
const existingUser = await User.findOne({
username: user.username
});
if (existingUser) {
// user exists. generate token and login user
console.log('Existing user login');
const token = existingUser.generateAuthToken();
return res.status(200).json(successResponse(token));
} else {
console.log('New user login');
const savedUser = await new User(user).save();
const token = savedUser.generateAuthToken();
return res.status(200).json(successResponse(token));
}
} catch (e) {
console.log(e);
return res.status(400).json(failureResponse(errorcodes.ERROR_SERVER_ERROR, "Unable to login user"));
}
};
module.exports = {
loginUserController
};
Here the issue is when I try to hit the login route from Postman, I am getting an error which says Could not get any response.
But when I hit the rand route, the output is correct.
So the issue isn't the arrangement of the code.
Why am I not able to use the login route here?

Resources