req.body is undefined - only default mongodb id is getting pushed - javascript

I have been trying to use post request to insert data to the mongodb using mongoose, however I see that req.body is being shown as undefined. document is getting inserted in database, however only default object id is getting inserted.
This is how I send request to Postman
{
name:"wewe",
price:43}
//Post.js
const mongoose = require('mongoose');
mongoose.connect("mongodb://localhost/tutorialkart");
const productSchema = mongoose.Schema({
name: String,
price: Number
});
module.exports = mongoose.model('Groduct', productSchema);
//app.js
var express = require('express')
var bodyParser = require('body-parser')
var Post = require('./Post')
var app = express()
app.use(bodyParser.json())
app.post('/api/posts', function (req, res, next) {
var post = new Post({
name: req.body.name,
price: req.body.price
})
console.log("Log "+post.name );
post.save(function (err, post) {
if (err) { return next(err) }
res.json(201, post)
})
})
app.listen(3000, function () {
console.log('Server listening on', 3000)
})

There are two issues with your request in Postman (you removed the screenshot which showed these issues):
it's not formatted as proper JSON, but as a Javascript object
you're sending it as text/plain, not application/json

This is how I send request to Postman
{ name:"wewe", price:43}
One of two things is happening:
Either you aren't setting a Content-Type header in the request so the JSON parsing middleware you set up isn't being triggered or
You have, but since your JSON is invalid, it is failing to parse it.
You have to write valid JSON!
You can test your JSON with JSON Lint.
In particular, property names in JSON must be strings and cannot be identifiers. Strings in JSON must be delimited with " characters.

Your screenshot is not visible/trouble opening the screenshot. You need to be more specific with your question.
I think mongoose.connect("mongodb://localhost/tutorialkart"); here you need to specify the PORT localhost:27017
Make sure you defined the names "name" and "price" in your HTML/EJS and setting their value as the data you are trying to insert into database.
Use new before mongoose.model, mongoose.Schema
app.use(bodyParser.json()) should be app.use(bodyParser.urlencoded({ extended: true }));

Related

Req.body is empty for POST request in Express

I try to use Postman for generating some post transaction of my web but when I check the post method of my code it print the empty {} and add the empty {} to my list. I try to use middleware but the problem is still occurring.
This is my code.
// my code at restaurant.js
const express = require("express");
const router = express.Router();
const restaurants = require("../data")
router.get("/",(req,res) =>{
res.json(restaurants);
}
)
router.get("/:id",(req,res) =>{
const restaurantid = Number.parseInt(req.params.id,10);
const restaurant = restaurants.find((restaurant) => restaurant.id === restaurantid);
res.json(restaurant);
})
router.post("/",(req,res)=>{
console.log(req.body);
new_restaurant = req.body;
restaurants.push(new_restaurant);
res.json(new_restaurant);
}
)
module.exports = router;
//my code at index.js
const express = require("express");
const app = express();
const router = express.Router();
const restaurantsRouter = require("./routes/restaurants.js");
// Middleware
app.use(express.json());
app.use(express.urlencoded({extended:false}));
// Routes
app.use("/apis/restaurants",restaurantsRouter);
app.get("/",(req,res)=>{
res.send("<h1>Hello Express</h1>");
});
app.listen(3000,()=> {
console.log("Listening to port 3000");
})
module.exports = router;
The general reasons for an empty req.body on an incoming POST request are as follows:
You are failing to send the body properly with whatever client is sending the request.
You are failing to set the right content-type with the request that matches the type of the body data you are sending. If you're sending JSON, then you will need to make sure the incoming request has the content-type application/json.
You don't have the right middleware installed or working properly that will match the incoming content-type, read the body from the incoming stream, parse it and put the parsed results in req.body.
The middleware for parsing that content-type is not registered before your route handler in Express.
Some other middleware is "eating" the body before your middleware so the body is empty when it gets to your JSON middleware.
So, you will need to go through your POST request and eliminate each of these possibilities until you find the problem.

Express Server routing issue

I'm trying to add a new route to fetch a user by id but my error handling is not working correctly. Here is the code for that route.
const express = require('express');
require('./db/mongoose');
const User = require('./models/user');
const Task = require('./models/task');
const app = express();
const port = process.env.PORT || 3000;
app.use(express.json());
// ***removed code for brevity
// Route for fetching user by id
app.get('/users/:id', (req, res) => {
//console.log(req.params.id);
const _id = req.params.id;
User.findById(_id)
.then(user => {
//console.log(user)
if (!user) {
return res.status(404).send();
}
res.send(user);
})
.catch(e => {
res.status(500).send();
});
});
So if I test the route on Postman and I enter the correct user id from the database I get that user sent back, which is the the correct response. But if I enter an incorrect user id I get the 500 error code response instead of the 404 error code. The if (!user) statement is getting skipped and I can't figure out why. Any thoughts as to what I am missing?
Running this thru my own personal mongoose/express-using project, I get the following error:
UnhandledPromiseRejectionWarning: CastError: Cast to ObjectId failed for value "12345" at path "_id" for model "User"
That basically means Mongoose is expecting its own specific object type, an "ObjectId". This is a bit of a pain, since normally if you're using .findOne({_id:something), you can just use a string. If we do:
User.findById(mongoose.Types.ObjectId(_id))
it should work. Note that if you use an invalid id (like I obviously did here, it'll still error out. For that reason, I'd use the standard NodeJS format for callbacky stuff:
.then((err,result)=>{
//other stuff
});
In general, the .catch() block should only happen if obviously Mongoose and your router can't handle it.
EDIT: Also, for others info, Mongoose.model.findById is a built-in convenience method, and should basically do exactly what it says on the tin.

Send POST data with raw json with postman Express

I'm trying to log all the data and then return it as a response.
app.post('/data', (req, res) => {
const data = req.body
console.log(data)
return res.json({
data
})
})
I'm sending data with Postman. In the Body tab I have "raw" selected and "JSON (application/json)". Headers tab is Content-Type application/json. I'm sending this:
{
"aa": 23
}
When I click send button all I get is an empty object and the data variable is undefined in my console.log. How to fix it? I double checked everything. It should work, but it doesn't.
It seems like you're passing an invalid value to res.JSON(). Try:
return res.json(data);
Alright, I found the solution.
"As body-parser module is used to parse the body and urls, it should be called before any call to 'req.body...'."
So I did this:
import bodyParser from 'body-parser'
const app = express()
app.use(bodyParser.urlencoded())
app.use(bodyParser.json())
app.post('/data', (req, res) => {
const data = req.body
console.log(data)
return res.json({
data
})
})
And now it works fine.

Node.js unable to read POST JSON data in my webhook

I have a node.js + Express application. It has a webhook that I have provided to a third party service. The service sends a POST request to my webhook with JSON body which looks something like this:
{"split_info" : "null", "customerName" : "Merchant Name",
"additionalCharges" : "null", "paymentMode":"CC",
"hash":"a31ff1b91fd9b8ae9c82f38b02348d21fsdfd86cc828ac9a0acf82050996372cc656de3db0fe3bf9af52b73a182a77787241f3e19ec893391607301b03e70db8",
"status" : "Release Payment", "paymentId" : "551731" ,
"productInfo":"productInfo", "customerEmail":"test#gmail.com",
"customerPhone":"9876543212", "merchantTransactionId":"jnn",
"amount":"100.0", "udf2":"null", "notificationId" :"4", "udf1":"null",
"udf5":"null", "udf4":"null", "udf3":"null","error_Message":"No
Error"}
I am using body-parser module to read POST data. However when I do req.body it gives [object Object], if I do JSON.stringify(req.body), it gives {} i.e. empty. If I try to access the keys in the response like req.body.paymentMode then it gives undefined.
Here is my router code for the webhook: mywebhook.js
var express = require('express');
var router = express.Router();
router.post('/success', function(req, res){
//this is where I need to strip the JSON request
//req.body or JSON.stringify(req.body) or anything that works
//if everything is okay then I send
res.sendStatus(200);
});
module.exports = router;
My app.js looks like this:
var express = require('express');
var exphbs = require('express-handlebars');
var router = express.Router();
var bodyParser = require('body-parser');
var mywebhook = require('./routes/mywebhook');
var app = express();
.
.
.
app.use(bodyParser.urlencoded({'extended':'true'})); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // parse application/json
app.use(bodyParser.json({ type: 'application/vnd.api+json' })); // parse application/vnd.api+json as json
app.use('/callwebhook', mywebhook);
.
.
.
so on
Pretty sure I am missing something or doing something wrong, but I am not able to figure it out.
Thanks.
I finally found what was going on.
The way the body-parser works is that it will only try to parse a request in which they understand the Content-Type. This is mainly so you can stack them (app.use multiple parser types without conflict) and also because you typically don't want to parse a request that's going to fail (Content-Type: text/html is unlikely to ever get through a JSON.parse, for example).
I ended up getting sent */*; charset=UTF-8 which is not even a valid Content-Type header value period. The body-parser module refused to accept it, since that is gibberish. This module does allow you to setup a function that lets you put any custom logic you want to perform the filtering.
I had to put the body parser in my router code just for this webhook case.
var bodyParser = require('body-parser');
var customParser = bodyParser.json({type: function(req) {
return req.headers['content-type'] === '*/*; charset=UTF-8';
}});
router.post('/success', customParser, function(req, res){
console.log(JSON.stringify(req.body));
});
#svens thank you for your help.

Attempting to send object from client to server (AngularJS $http.post)

I'm attempting to store an object that my user clicks on in my server so that when the page changes, all the information from that object can be displayed fully in a profile page.
I'm unfamiliar with Angular $http but I've tried to write a call that will POST to the server, unfortunately when I scan through the req object in VScode I can't find where the object I sent is contained, so I can send it on to my function.
Controller function:
$scope.storeProfile = function(child){
$http.post('/storeTempProfile', child)
.then(function(response) {
window.location.href = 'DemoPage.html';
});
}
server.js:
app.post('/storeTempProfile', function (req, res) {
profileStorage.storeProfile(req);
});
does my app.post look right? And what property of req do I need to use the dot operator on to access my object? I can't seem to find the object data anywhere in req and that makes me thing there's something wrong with how I wrote app.post
It looks like you are using express. So in that case, you want to access the object on req.body, but this will require you use body-parser. The example on their homepage:
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// create application/json parser
var jsonParser = bodyParser.json()
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
if (!req.body) return res.sendStatus(400)
// create user in req.body
})
You will notice in this example that they pass the json parser into the route itself. This is only necessary if you want to have different parsers for different routes. Usually you just want to set it to all routes, which you can do by using app.use(bodyParser.json()).

Categories