How to save data in mongodb with express node.js? - javascript

I am encountering a problem when I try to make a post request with mogoose using the Postman, i get the following answer:
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>
I can't understand the reason, my index.js code:
const express = require("express");
const mongoose = require("mongoose");
const cors = require('cors')
const bodyParser = require('body-parser')
mongoose.connect(
process.env.MONGODB_URL || "mongodb://localhost/trading",
{
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
}
).then(item => {
console.log('conectado com o banco')
}).catch((err)=>{
console.log(err)
});
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}))
const candlesRoute = require("./routes/candles");
const home = require("./routes/home");
app.use((req, res, next) => {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", 'GET,PUT,POST,DELETE');
app.use(cors());
next();
})
app.use("/", home);
app.use("/candles", candlesRoute);
const PORT = 8080;
app.listen(PORT, () => {
console.log("Servidor Conectado");
});
my route candles.js :
const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
require("../models/Candles");
const candlesTick = mongoose.model("candles");
router.post('/candles', async (req, res) => {
try {
const velas = req.body
await new candlesTick(velas).save();
console.log('successe')
} catch (error) {
console.log(error);
}
});
module.exports = router;
and finally my model Candles.js:
const mongoose = require('mongoose')
//const Schema = mongoose.Schema
const Candles = new mongoose.Schema({
titulo: {
type: String,
},
})
mongoose.model("candles", Candles);
my request in the Postman is as follows
{
"titulo": "DENT/ETH"
}
I have already tmbm send the data directly and even then it does not work, I do not understand the reason for this, please if anyone can help thanks

app.use("/candles", candlesRoute); will add namespace to that route and router also has candles in the post request. At the end the available route will be POST {{host}}/candles/candles.
Please try remove candles from
router.post('/candles', async (req, res) => {
...
})
or have the URL in postman as {{host}}/candles/candles

I think req.body is not parsed, because you've set bodyparser extendedUrl to false. Try this:
app.use(bodyParser.urlencoded({extended: true}))
Also you simply create your object with MyModel.create(myContent) instead of using new Model() + save().

you should have posted your terminal logs also but nvm :)
I can guess the problem by looking at your code : -
Your mongodb local URL is wrong there is no mention of port.
it is always like mongodb://localhost:27017/trading for local server
I have less idea about this but you didn't export model in Candles.js

Related

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 to set different bodyparser on specific express route

I am using express 4.
in my server.js I have express.json() middleware
require('dotenv').config();
const express = require('express');
const cors = require('cors');
const mongoose = require('mongoose');
const errorHandler = require('./_helpers/error-handler');
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json()); /////////////////////////////////////////
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: true});
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDB database connection established successfully");
});
// routers
app.use('/api/users', require('./routes/api/users/users.controller'));
app.use('/api/orders', require('./routes/api/orders/orders.controller'));
app.use('/shopify/app', require('./routes/shopify/app/shopify.controller'));
app.use('/shopify/app/webhooks', require('./routes/shopify/app/webhooks/webhooks.controller')); ///////////////
app.use(errorHandler);
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
but for '/shopify/app/webhooks' route I need to get raw body so I can create hash
but so far I am receiving Object because I have express.json() middleware.
this is my webhooks.controller.js file
const express = require('express');
const router = express.Router();
const crypto = require('crypto')
const SHOPIFY_API_SECRET_KEY = process.env.SHOPIFY_API_SECRET_KEY;
// router.use(express.raw({ type: "application/json"}));
// routes goes here
router.post('/app/uninstalled', express.raw({ type: 'application/json' }), async (req, res, next) => {
const hmac = req.get('X-Shopify-Hmac-Sha256')
console.log(req.body);
// create a hash using the body and our key
const hash = crypto
.createHmac('sha256', SHOPIFY_API_SECRET_KEY)
.update(req.body, 'utf8', 'hex')
.digest('base64')
// Compare our hash to Shopify's hash
if (hash === hmac) {
// It's a match! All good
console.log('Phew, it came from Shopifify!')
res.sendStatus(200)
} else {
// No match! This request didn't originate from Shopify
console.log('Danger! Not from Shopify!')
res.sendStatus(403)
}
})
what I have tried is in webhooks.controller.js router.use(express.raw({type: "application/json"}))
i thought since I am receiving json object I can use express.raw() middleware that accepts json
but it's still not working.
You have to place this route BEFORE your app.use(express.json()) middleware and then you can apply the raw middleware directly to that route:
app.use('/shopify/app/webhooks', express.raw({/* put your options here */}), require('./routes/shopify/app/webhooks/webhooks.controller'));
Keep in mind that this line of code must go physically before your express.json() middleware.
We can get useful info for specific routes before applying body parser.
So, if you want to get raw body for stripe webhooks.
We can do like this.
app.use(bodyParser.json({
extended: true,
verify: function (req, res, buf) {
if (req.originalUrl.endsWith('/stripe/webhooks')) {
req.rawBody = buf
}
}
}))

Failed to connect to localhost 5000

I am trying to connect my node app with MongoDB. The code seems to execute as I get the output
Server is running on port 5000
MongoDB database connection established successfully
on the terminal
But when I try to post get from insomnia it takes about two minutes before I get the error
Error: Server returned nothing (no headers, no data)
const express = require('express');
//const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect( uri, {useUnifiedTopology: true, useNewUrlParser: true}, () => { console.log("MongoDB database conection established successfully")}).catch(err => console.log(err));
const exercisesRouter = require('./routes/exercises');
const usersRouter = require('./routes/users');
app.use('/exercises', exercisesRouter);
app.use('/users', usersRouter);
//emitter.setMaxListeners();
app.listen(port, () => {
console.log('Server is running on port : ' + port);
});
I am following a tutorial and these are the other files I have
exercise.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const exerciseSchema = new Schema({
username: {type: String,required: true},
description: {type: String,required: true},
duration: {type: Number,required: true},
date: {type: Date,required: true},
},
{
timestamps: true,
});
const Exercise = mongoose.model('Exercise', exerciseSchema);
module.exports = Exercise;
exercises.js
const router = require('express').Router();
let Exercise = require('../models/exercise.model');
router.route('/').get((req, res) => {
Exercise.find()
.then(exercises => res.json(exercises))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req, res) => {
const username = req.body.username;
const description = req.body.description;
const duration = Number(req.body.duration);
const date = Date.parse(req.body.date);
const newExercise = new Exercise({
username,
description,
duration,
date,
});
newExercise.save()
.then(() => res.json('Exercise added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
module.exports = router;
users.js
const router = require('express').Router();
let User = require('../models/user.model');
router.route('/').get((req,res) => {
User.find()
.then(users => res.json(users))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req,res) => {
const username = req.body.username;
const newUser = new User({username});
newUser.save()
.then(() => res.join('User added!'))
.catch(err => res.status(400).json('Error: ' + err));
})
module.exports = router;
user.model.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
username: {
type: String,
required: true,
unique: true,
trim: true,
minlenght: 3
},
},{
timestamps: true,
});
const User = mongoose.model('User', userSchema);
module.exports = User;
I also get Cannot GET / when I go to http://localhost:5000 on my browser and in the inspector errors it says Refused to load the image 'http://localhost:5000/favicon.ico' because it violates the following Content Security Policy directive: "default-src 'none'". Note that 'img-src' was not explicitly set, so 'default-src' is used as a fallback. This may be a lot but I am trying to learn how to connect backend with front end and would appreciate it if someone can guide me. Thank you in advanced.
The problem seems to be CORS related. This means that the express API you have created, will not accept calls from other domains and expects the interaction to come from the same application. As you are are using insomnia, which is a separate desktop app or something, express will block access to routes. This is the default behavior.
You need to grab the CORS middleware and set up your routes as needed. Just follow the docs.
A quick test to allow all access:
const express = require('express');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/users', (req, res) => {...
...
Ther is an other method to add CORS
app.use(function (req, res, next) {
//Enabling CORS
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type,
Accept, x-client-key, x-client-token, x-client-secret, Authorization");
next();
});
I'm also going through the same tutorial: https://www.youtube.com/watch?v=7CqJlxBYj-M
The problem is with app.use(express.json());
Comment that out and it'll work fine. But then you won't be able to parse JSON data when you're doing post requests. I'm not sure why express.json() doesn't work.
But either way you can use Body-Parser to solve that problem. First user npm i body-parser to install it to your package manager in your backend folder. Then copy the below code to your index.js
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({extended: true}))
app.use(bodyParser.json())
add this code and you'll be fine. This answer gives a detailed explanation of express.json & body-parser.
express.json() is a method inbuilt in express to recognize the incoming Request Object as a JSON Object.
I recommend using body-parser (it is an NPM package) to do the same thing. It is developed by the same peeps who built express and is designed to work with express. body-parser used to be part of express.

Why do I get the PUT request with POSTMAN not done?

Before embarking on the routes of my application, I have created some requests with POSTMAN of which PUT is not made to me in full.
This is my configuration of my server in ExpressJS:
const express = require('express');
const morgan = require('morgan');
const helmet = require('helmet');
const mongoose = require('mongoose');
const app = express();
// Settings
app.set('port', process.env.PORT || 3000);
mongoose.connect('mongodb://localhost/mevn-curso', {
useNewUrlParser: true,
useFindAndModify: false,
useCreateIndex: true
})
.then(db => console.log('DB is connected'))
.catch(err => console.log(err));
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
// Middlewares
app.use(morgan('dev'));
app.use(express.json());
app.use(helmet());
// Routes
app.use('/tasks/', require('./routes/tasks'));
// Static files
app.use(express.static(__dirname + '/public'))
app.listen(app.get('port'), ()=> {
console.log('Server on port', app.get('port'));
});
It works for me normally and this is the router I am using, which is inside the tasks.js file in the routes folder:
const express = require('express');
const router = express.Router();
const Task = require('../models/Task');
router.get('/', async (req,res)=> {
const tasks = await Task.find();
res.json(tasks);
})
router.post('/', async (req,res) => {
const task = new Task(req.body);
await task.save();
res.json({
status: "Task Saved"
})
})
router.put('/:id', async (req,res)=> {
console.log(req.params._id);
console.log(req.body);
await Task.findByIdAndUpdate(req.params._id, req.body)
res.json('recivied');
console.log('Listo')
})
module.exports = router;
In console does not seem to give me any error. I make the request with normal POSTMAN, and it returns the logs of the console. Even the server answers the json and everything. But the data in the database is not changed. This does not happen with GET or POST, on the contrary, everything is going well.
Here I leave you how I make the request with POSTMAN. First of all I am going to show you the data that I already have in the database, with the get request that is normally done with the browser:
ready, when I'm making the PUT request this is my configuration in POSTMAN:
It's a json type content type because that's what I'm going to process, then comes the body:
and this is the answer in the console:
What do you think it could be?
as I see the console.log of req.params._id is undefined: change the
Task.findByIdAndUpdate(req.params.id, req.body) changed _id to id
router.put('/:id', async (req,res)=> {
console.log(req.params.id);
console.log(req.body);
await Task.findByIdAndUpdate(req.params.id, req.body)
res.json('recieved');
})

Express request doesn't end

i made a very simple api using express.js. Here's the code:
var express = require('express');
var app = express();
var morgan = require('morgan');
var UserModel = require('../Models/User')
app.use(morgan('short'));
app.use(express.json());
app.get('/getAll', (req, res) => {
res.status(200).json({auth: true});
})
app.post('/addUser', (req, res) => {
const { name, email, password } = req.body;
UserModel.create({name, email, password}, (err, user) => {
if(err) return res.status(500).end({auth: false})
res.status(200).end({user});
});
});
module.exports = app;
And here's the userModel:
const mongoose = require("mongoose")
const Schema = mongoose.Schema;
const UserSchema = new Schema(
{
name: String,
email: String,
password: String,
},
{timestamps: false}
);
mongoose.model("User", UserSchema);
module.exports = mongoose.model("User");
This is the main server.js file:
var express = require('express');
var app = express();
const AuthController = require("./Controllers/AuthController");
const PORT = 3001;
app.use("/api/auth", AuthController);
app.listen(PORT, () => console.log(`Listening on port ${PORT}..`))
This is the db.js file:
const mongoose = require('mongoose');
const dbRoute = "mongodb://<user>:<password>#<stuff>/nodejs-db";
mongoose.connect(
dbRoute,
{useNewUrlParser: true}
);
So here's the problem. when i try to make a request to this api using Insomnia, the requests doesn't end. Basically Insomia starts sending the request and i have to wait like 20 secs until i get something on my express terminal. If i end the request manually i get this:
::ffff:127.0.0.1 - POST /api/auth/addUser HTTP/1.1 - - - - ms
I tried looking online but couldn't find anything useful.
I come from a django backgrond. I'm new to Node and Express js.
Edit:
The problem is only with the posts requests because whenever i make a get request it returns immediately {auth: true}.
Change your .end() to .send()
app.post('/addUser', (req, res) => {
const { name, email, password } = req.body;
UserModel.create({name, email, password}, (err, user) => {
if(err) return res.status(500).send({auth: false})
res.status(200).send({user});
});
});
I solved this problem.
Apparently the problem was that my db connection was on another file.
All i did was to move the content from the db.js file to my server.js file.
I forgot to include my db file.

Categories