My backend route is not behaving as it should and not posting anything to MongoDB - javascript

I am trying to create a simple CRUD app. I was trying to set up the first backend route but I am stuck and can't figure out what is wrong with my code or what I am missing.
If I try to test the route with Insomnia, it doesn't return any error, but it targets the basic "/" route and returns the console.log('OK') instead of creating an item in MongoDB. Here is my code:
// app.js file
require("./db");
const express = require("express");
const app = express();
require("./config")(app);
const backoffice = require('./routes/backoffice');
app.use('/api/backoffice', backoffice);
app.use('/', (req, res) => {
res.send('OK')
});
module.exports = app;
// route file backoffice.js
const router = require("express").Router();
const Item = require("../models/Item");
router.post('/backoffice', (req, res, next) => {
console.log(req.body);
const {title, description} = req.body;
Item.create({
title,
description
})
.then(response => {
console.log(response)
res.status(200).json({message: 'New item added succesfully'})
})
.catch(err => res.json(err))
})
module.exports = router;

Related

node js post 404 not found with router

hello i have a issue i build a project when i start to add the server side
i am using node js express
i create fetch post to spesific url from the database (mongoDB)
and i want to add the users
now
its workd but i try to reconfigure the files and using router and now i get 404 when i try to make the post is upload some code
just need to know where is the bad request
the url i want to fetch is
http://localhost:5000/shopping-cart/user/sign-up
Axios.post("http://localhost:5000/shopping-cart/user/sign-up", user).then((response) => {
console.log(response);
});
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const path = require("path")
const productRouter = require("./routes/product.route");
const userRouter = require("./routes/user.route");
const { setServerConfiguration } = require("./config");
setServerConfiguration(app);
mongoose.connect('mongodb://localhost/shopping-cart-data-base');
app.use("/shopping-cart", productRouter);
app.use("/user/sign-up", userRouter);
app.listen(5000);
const router = require('express').Router();
const errorsHandler = require('../utils/errorsHandler');
const UserModel = require('../models/User');
router.post("/user/sign-up", async (req, res) => {
let body = req.body;
console.log(body)
try{
await UserModel.create({
name: body.name,
username: body.username,
password: body.password,
shoppingHistory: [],
});
res.send(body);
}catch(e){
return errorsHandler(e, req, res);
}
});
module.exports = router;
Your router is mounted on the /user/sign-up prefix:
app.use("/user/sign-up", userRouter);
Which means that all requests that start with /user/sign-up will get passed to your router.
Your router should be routing relative to that prefix, so to make it work, use this:
router.post('/', ...)
Try this url
"http://localhost:5000/user/sign-up"
If you want to use "http://localhost:5000/shopping-cart/user/sign-up" than you need to define route like that, for example:
router.post("shopping-cart/user/sign-up", async (req, res) => {
//Your code
})
404 route not found
app.use("/shopping-cart", productRouter) => route1
app.use("/user/sign-up", userRouter); => route2
route1 other route2
url http://localhost:5000/shopping-cart request route1
url http://localhost:5000/user/sign-up request route2

to be under different domain, why axios.post dont work

https://github.com/skyturkish/e_commerce_advance this is the repo
index.js
const express = require('express')
const bodyParser = require('body-parser')
const UserService = require('./services/user-service')
const app = express()
app.set('view engine', 'pug')
app.use(bodyParser.json())
app.get('/', (req, res) => {
res.render('index')
})
app.get('/users/all', async (req, res) => {
const users = await UserService.findAll()
res.render('user', { users })
})
app.get('/users/:id', async (req, res) => {
const user = await UserService.find(req.params.id)
res.send(user)
})
app.post('/users', async (req, res) => {
const user = await UserService.add(req.body)
res.send(user)
})
app.delete('/users/:id', async (req, res) => {
const user = await UserService.del(req.params.id)
res.send(user)
})
app.listen(3000, () => {
console.log('Server listening')
})
When I try to add a new user under "http://localhost:3000/" or "http://localhost:3000/users/all", this works. But under http://localhost:3000/users/1 throw an error. I cant understand well, why this happens, how does being under a domain authorize and receive it.
The GET handlers for / and /users/all use res.render(), but the GET handler for /users/:id uses res.send() (so it doesn't render your template, which in turn loads the axios library).

req.body is empty, why?

I want to send some data to my MongoDB database, but in router.post my req.body is empty, if I use stuff that I put in my send function in User(req.body) instead of req.body data will be send to my MongoDB database correctly.
This is my router that I use, router.get work fine, it return database tables correctly on /api page:
const router = require("express").Router();
const User = require("./model/models");
const parser = require("body-parser").json();
router.get("/", async (req, res) => {
const data = await User.find({});
res.json(data);
});
router.post("/",parser,async (req, res) => {
console.log('1')
console.log(req.body)
console.log('2')
parser.v
await User(req.body).save();
res.json({"msg": "ok"});
});
module.exports = router
This is my index.js file code:
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
const parser = require("body-parser").json();
var path = require('path');
app.use(express.urlencoded(true));
app.use(express.json());
app.use(parser);
app.use('/',require("./routes/routes"))
app.use(express.static(__dirname +'/public'))
app.use("/api", require('./data/api'))
app.listen(5000,function(){
console.log('server is alive')
})
This is function that what I use to send data:
const btn1 = document.getElementById('btnEnter')
let Login = "123"
btn1.addEventListener('click' ,e=>{
send({newsTxT : "someTextHere",newsZag:"someZag",author:"SomeAuthor"})
})
const send = async(body) => {
let res = await fetch("/api", {
method: "post",
header: {
"Content-Type": "application/json",
"Accept": "application/json"
},
body: JSON.stringify(body)
});
let data = await res.json();
console.log(data)
}
The only weird thing I see is that you are using a json body-parser and also the express.json() both technically do the same, but body-parser is deprecated so it might be causing a bug.
Also you don't have to import it again in the routes, placing app.use(express.json()) at index.js will make it work for all endpoints/routes.
See how this refactor goes:
const router = require('express').Router()
const User = require('./model/models')
router.get('/', async (req, res) => {
const data = await User.find({})
res.json(data)
})
router.post('/', async (req, res) => {
console.log('1')
console.log(req.body)
console.log('2')
await User(req.body).save()
res.json({ 'msg': 'ok' })
})
module.exports = router
index.js
const express = require('express')
const app = express()
var path = require('path')
app.use(express.urlencoded(true))
app.use(express.json())
app.use('/', require('./routes/routes'))
app.use(express.static(__dirname + '/public'))
app.use('/api', require('./data/api'))
app.listen(5000, function () {
console.log('server is alive')
})
The following worked fine:
const express = require("express")
const app = express()
const router = express.Router()
router.use(express.json())
app.use(router)
router.post('/api/user', function(req, res) {
// ...
}
I see the difference may be using the: app.use(router)
Note that in the above code the statement:
router.use(express.json())
can be replaced with (using the body-parser):
const bodyParser = require('body-parser')
router.use(bodyParser.json())
This worked fine with express version 4.17.1, body-parser version 1.19.0 and NodeJS version 12.18.3

How can we implement an admin panel in nodeJS with express?

I am making a Portfolio application with nodeJS and express. I want to implement an admin panel which I can create,delete, update and edit my skills,experience,about etc, but I don't know how can I keep those admin routes secret and what kind of authentication to make.If we can do by putting Basic authentication on post,patch,delete route then how will we implement basic authentication on routes.
index.js
const express = require('express');
const app = express();
var cors = require('cors');
require('./db/mongoose')
const menuRouter = require('./routers/menu')
const skillRouter = require('./routers/skill')
const aboutRouter = require('./routers/About')
const experienceRouter = require('./routers/Experience')
const resumerouter = require('./routers/Resume')
const userRouter = require('./routers/user')
const port = process.env.PORT || 4000;
app.use(express.json());
app.use(cors());
app.use(menuRouter);
app.use(skillRouter);
app.use(aboutRouter);
app.use(experienceRouter);
app.use(resumerouter);
app.use(userRouter)
app.listen(port, () => {
console.log("Server is runing on port" + port)
});
skill.js
const express = require('express');
const Skill = require('../model/skill');
const router = new express.Router();
router.post('/skill', async (req, res) => {
const skill = new Skill(req.body);
try {
await skill.save();
res.status(201).send(skill);
} catch (e) {
console.log(e);
res.status(400).send(e);
}
})
router.get('/skill', async (rq, res) => {
try {
const skill = await Skill.find({});
res.status(201).send(skill);
} catch (e) {
res.status(400).send(e);
}
})
module.exports = router;
As specified in the comments, I would refactor your code a bit, seems messy and you're kind'a repeating yourself every line you import a route, so, you should do it better as well...
have an index.js file in your /routers folder with the content of the demo repo I've made for other StackOverflow question
then, to separate things, I would do something like:
const routes = require('./routes')
...
const protectRouteWithApiKey = (req, res, next) => {
const auth = req.headers['x-apikey']
if (auth && auth === '<YOUR API KEY>') return next()
return next(new Error('403 | Authorization is missing or value is wrong'))
}
...
app.use('/api', protectRouteWithApiKey, routes) // point to your routes and protect access
app.use('/', defaultEngine) // your engine to render html
you would then have a protected route in /api/* and normal routes for everything else
A middleware where you detect if the logged user is the admin?
In this sample checking by the email, and you can save the adminemail as a global variable
ensureAdmin: function(req, res, next) {
if (req.isAuthenticated()) {
if (req.user.email === adminemail) {
return next();
} else {
return res.redirect('/adminsecretroute');
}
}
res.redirect('/');
}

Route.delete() requires a callback function but got a [object Object]

I have node-express app where I have bunch of Routes for login, logout and signup and one Route for checking authorised Route which can be accessed only through providing authToken. I moved the Routes to separate Route file and I got the above error.
This is my Users Routes File:
const express = require('express');
const authenticate = require('./../middleware/authenticate');
const router = express.Router();
const {User} = require('./../models/user');
router.post('/',(req, res) => {
var body = _.pick(req.body,['email','password']);
var user = new User(body);
user.save().then(() => {
return user.generateAuthToken()
}).then((token) => {
res.header('x-auth', token).send(user);
}).catch((e) => {
res.status(400).send(e);
});
});
router.post('/login',(req, res) => {
var body = _.pick(req.body, ['email', 'password']);
User.findByCredentials(body.email, body.password).then((user) => {
return user.generateAuthToken().then((token) => {
res.header('x-auth', token).send(user);
});
}).catch((e) => {
res.status(400).send(e);
});
});
router.delete('/logout',authenticate, (req, res) => {
req.user.removeToken(req.token).then(() => {
res.status(200).send();
},(e) => {
res.status(400).send(e);
}) ;
});
router.get('/me',authenticate, (req,res) => {
res.send(req.user);
});
module.exports = router;
Following is my main server.js file:
const express = require('express');
const _ = require('lodash');
var app = express();
const usersRoutes = require('./routes/users');
app.use(express.json());
app.use('/users', usersRoutes);
var {mongoose} = require('./db/mongoose');
var {User} = require('./models/user');
var {authenticate} = require('./middleware/authenticate');
const port = process.env.PORT || 3000 ;
app.listen(port, () => console.log(`Listening on ${port}...`))
I have a model/Schema(mongoose) file for User so If You feel you need that I am ready to edit my question. Thanks.
The problem is that router.delete is expecting a function on the middleware parameter (like you did in your server.js file with app.use(express.json())) so it can be used like a callback which gets called whenever a request reach your route.
Try changing authenticate to authenticate().
It seems like in your users routes file you are importing the entire module who contains the authenticate function, so when try to access it like a function you'll get an error. You need to import it like you did in your server.js file.
Change the line const authenticate = require('./../middleware/authenticate'); for const {authenticate} = require('./../middleware/authenticate');.

Categories