Body is undefined when parsing JSON in Express.js - json

I have a simple server where i just prints a json to the screen when its posted. This is my code:
/*jslint node:true*/
var express = require('express');
var app = express();
app.use(express.json());
app.use(app.router);
app.post('/event', function (res, req) {
//'use strict';
console.log(req.body);
});
app.listen(3000);
Then i put a JSON to the server with curl:
curl -X POST -H "Content-Type: application/json" -d '{"username":"xyz","password":"xyz"}' http://localhost:3000/event
But the server just prints undefined
What am i doing wrong?

you haven't defined usage of
express.bodyParser()
it has to be done like this:
app.use(express.bodyParser());
live example:
module routes file
exports.post = function(req, res){
console.log(req.body);
//res.render('index', { title: 'Express' });
};
application:
app.post('/post', routes.post);
fiddler request:
from comments: in case you have latest libs, you should take into account that bodyParser is deprecated from Connect 3.0. appropriate thread: How to get rid of Connect 3.0 deprecation alert?

I just figured out what the problem is. It should be:
function (req, res)
and not:
function (res, req)
since the first parameter is the request and the second is the response.

Related

Post an array into MySQL Workbench with Express.js api and mysql package

I'm working with Express.js and mysql package to create my apis, but i can't make a post.
This is my code so far:
const express = require('express');
const mysql = require('mysql');
const config = mysql.createConnection({
host: theHost,
port: thePort,
user: theUser,
password: thePass,
database: theDB,
});
const app = express();
config.connect(function(err){
if(!err) {
console.log("Success");
} else {
console.log("Error trying to connect");
}
});
app.get("/api/InternalAccess", function(req, res){
config.query('SELECT * from InternalAccess', (error, result) => {
if (error) throw error;
res.send(result);
});
});
app.post("/api/internalAccess", function(req, res){
var info = { User: req.body.User, Password: req.body.Password, CreationDate: req.body.CreationDate };
config.query('INSERT INTO InternalAccess SET ?', info, (error, result) => {
if (error) throw error;
res.send(result);
});
});
app.listen(3000);
I have no problems with get, it works fine, but to make post from postman, i get the error: " Cannot read property "User" of undefined". Am i avoiding something? I'm really new using mysql package.
My db is MySQL Workbench, and as i said, i'm using Node.js, Express.js and mysql package.
Hope you can help me. Thanks in advance
In order to have req.body populated automatically, you have to use some body-parser middlewares, like:
app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded
Of course, there can be multiple other causes (like, you're not constructing the request properly in postman), but the lack of setting the middlewares is the first place I'd fix.
Seems like req.body is null. I think you might just be missing the body-parser in your app.js.
var bodyParser = require('body-parser');
var app = express();
// parse application/json
app.use(bodyParser.json())
see other examples here: https://expressjs.com/en/resources/middleware/body-parser.html

How to get JSON Data sent through postman tool using post method?

I'm trying to get a JSON data which is sent as JSON data using postman tool and trying to receive it my post() method.
var express = require('express');
var app = express();
app.post('/myData',function(req,res){
console.log("--->",req.body);
});
var server = app.listen(8080,function(){});
This is the JSON data sent through postman tool
I'm getting undefined in my console as
"---> undefined"
I'm trying to retrieve the JSON data set in my postman tool to either my console or browser
Corrected. Please try to run this code.
var express = require('express');
var app = express();
app.post('/myData', function (req, res) {
req.on('data', function (data) {
console.log("--->",data.toString());
res.send("Received");
});
});
var server = app.listen(8080, function () { });
Add res.send(req.body); inside the app.post method.
app.post('/myData',function(req,res){
console.log("--->",req.body);
res.send(req.body);
});
Express usually uses a middleware called body-parser to parse the received JSON content. req.body will be empty if you don't enable body-parser or something similar. body-parser is built in for the latest versions of Express. It's enabled like this:
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
So the final code is like this:
var express = require('express');
var app = express();
app.use(express.urlencoded({ extended: false }));
app.use(express.json());
app.post('/myData',function(req,res){
console.log("--->", req.body);
res.send('data received');
});
var server = app.listen(8080,function(){});
I've also added res.send('data received');, because you should send a response when you get a request on a valid endpoint.

Logging all requests in Node.js/Express

In my small node.js application, using express, I wanted to log all the incoming requests, so I ended up with this:
var bodyParser = require('body-parser');
module.exports = function(app) {
app.set("port", 50001);
app.set("json spaces", 2);
app.use(bodyParser.json());
app.use(function (error, req, res, next) {
app.logger.info("received from "+req.get("X-Forwarded-For")+" : "+req.method+" "+req.originalUrl+" (Authorization: "+req.get("Authorization")+")");
//does not work if json is malformed
//app.logger.info("content :"+JSON.stringify(req.body));
if (error /*instanceof SyntaxError*/) {
res.status(400);
app.logger.error(error);
res.json({ error:{msg: error.message}});
} else {
next();
}
});
app.use(app.auth.initialize());
};
Unfortunately, I only get the logs via the app.logger.info line when there's an error (in my case a malformed JSON string in the body). What am I missing here?
Expressjs adapts its functionality based on what type of callback you give it (this is not common in JS libraries so it is not surprising that people get confused by it).
If you do this where your callback has four arguments:
app.use(function(error, req, res, next) {...});
then Express assumes this is an error-only middleware handler and will only be called when there are errors. In the express doc, see the section labeled Error-handling middleware. Note this specific part of that page:
Define error-handling middleware functions in the same way as other
middleware functions, except with four arguments instead of three,
specifically with the signature (err, req, res, next)):
And, here's a whole section of the documentation devoted to error handling middleware.
If you use just three arguments:
app.use(function(req, res, next) {...});
then, it is a normal middleware that is called when there are not errors. I'm not sure if they provide a single way to get both. But, certainly as a workaround, you could put your logging code into a function and then call that function from two separate middleware handlers, one for errors and one for non-errors.
Use morgan https://github.com/expressjs/morgan
Install morgan
$ npm install morgan
Include morgan in the index.js or app.js or server.js file (The file that pointed by the script tag in the package.json)
var morgan = require('morgan')
Then add below before all the app call.
app.use(morgan('combined'))
Complete example
var express = require('express')
var morgan = require('morgan')
var app = express()
app.use(morgan('combined'))
app.get('/', function (req, res) {
res.send('hello, world!')
})
A sample output line looks like this:
::1 - - [31/May/2021:09:03:14 +0000] "GET / HTTP/1.1" 200 2078 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36"
DEBUG='*' or DEBUG='express:router' environment variable
It does not show a lot of information about the request, but it does show the path and method, which might be enough for basic applications, and is convenient as it does not require any extra setup.
DEBUG='*' enables all logs and is slightly easier to type:
DEBUG='*' ./app.js
or the more specific DEBUG='express:router' is what you will generally want in a complex application with a lot of middleware, otherwise the DEBUG='*' could produce mountains of output:
DEBUG='express:router' ./app.js
E.g. with the hello world:
#!/usr/bin/env node
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
Then as I play on the browser with different URLs I can see logs such as:
express:router dispatching GET / +3m
express:router query : / +0ms
express:router expressInit : / +0ms
express:router dispatching GET /asdf +10s
express:router query : /asdf +0ms
express:router expressInit : /asdf +0ms
finalhandler default 404 +3m
express:router dispatching GET /asdf?qwer=zxcv +17s
express:router query : /asdf?qwer=zxcv +0ms
express:router expressInit : /asdf?qwer=zxcv +0ms
finalhandler default 404 +17s
Documentation at: https://expressjs.com/en/guide/debugging.html
Tested on express 4.17.1.
npm install body-parser
npm install morgan-body
and use this snippet,
const express = require('express')
const morganBody = require("morgan-body")
const bodyParser = require("body-parser")
const app = express()
const port = 8888
// must parse body before morganBody as body will be logged
app.use(bodyParser.json());
// hook morganBody to express app
morganBody(app, {logAllReqHeader:true, maxBodyLength:5000});
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
You can just use grackle_tracking npm library to easily log all your traffic out to the console or log it to your database - also tracks uncaugt/caught errors - you can toggle it on/off easily for different environments as well since it's just
grackle_tracking.configure({...configuration...});
app.use(grackle_tracking.track);
so you can comment out both or just the bottom line for environments/users you don't want to track
https://www.getgrackle.com/libraries#grackle_tracking_overview
You could use try/catch
try {
var jsonBody = JSON.stringify(req.body);
app.logger.info("content :" + jsonBody);
} catch (err) {
app.logger.error("content error, error type: invalid json, error msg:" + err);
}

How parse JSON properties from request body in express server?

I've set up a node server that passes requests to a utility class.
So far the POST request is hit but the mapping to the body property values are undefined. Bodyparser is also used in the post method to assist in the Json parse.
I stepped into the request and see that the body is populated and see that the property names are correct as shown in the paste below:
body: { '{\n\t"Email":"brian#gmail.com",\n\t"Dashboard_Name":"my dash 4",\n\t''},
But the below mapping to the values assinged via req.body.propertyname return undefined:
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
Question:
How can you parse JSON properties from request body in express server?
JSON object posted:
This is the JSON that I post to the server using Postman:
{
"Email":"brian#gmail.com",
"Dashboard_Name":"my dash 4"
}
Gist of the express server and associated utility method SaveUserProfile:
Express server -
var express = require('express');
var UserLDAP = require('./utilities/UserLDAP'); //utility file containing the POST method
var bodyParser = require('body-parser');
const url = require('url');
const app = express();
var sql = require('mssql');
const cors = require('cors');
const path = require('path');
sql.connect("********************************************************************")
.then((connection1) => {
sql.globalConnection = connection1;
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/OOO/SaveUserProfile', UserLDAP.SaveUserProfile)
app.listen(process.env.PORT || 4000 );
logger.info(`listening to port ${process.env.PORT}`);
}).catch((err) => {
res.status(500).send(err.message);
logger.error(err.message);
});
UserLDAP.js -
var sql = require('mssql');
var bodyParser = require('body-parser');
//Save User Profile
exports.SaveUserProfile = function(req, res) {
req.app.use(bodyParser.json());
req.app.use(bodyParser.urlencoded({ extended: true }));
var request = new sql.Request(sql.globalConnection);
console.log(req);
var p_email = req.body.Email;
var p_dashboardName = req.body.Dashboard_Name;
};
Turns out I had incorrect content-type set in Postman on the object being posted. Needed to be set as:
application/json; charset=UTF-8
Currently you have no way of knowing if a parser like body-parser.json has produced an error which seems the obvious place to start given the content is there but the result isn't.
I had a look at body-parser and found an issue that spoke to the problem of detecting a json error which I would expect to be good to know.
The developer suggested the following as one method.
app.use(errorFork(bodyParser.json(),
function (err, req, res, next) {
// do stuff with only body parser errors
}))
// this is an example; you can use any pattern you like.
function errorFork(middleware, errorHandler) {
middleware(req, res, function (err) {
if (err) {
return errorHandler(err, req, res, next)
}else{
return next()
}
})
}
It isn't a fix but it would give you more info. Something is going wrong with the parsing by what you have indicated the questin is what? The other thing I noticed about your pasted body content is that it isn't valid json (ignoring \n\t) you have a few rouge ' in there, worth checking. Try copying what is in body (raw) and put it through a json validator site like jsonlint.com just as a double check and see if body-parser is returning any errors.

How do I consume the JSON POST data in an Express application

I'm sending the following JSON string to my server.
(
{
id = 1;
name = foo;
},
{
id = 2;
name = bar;
}
)
On the server I have this.
app.post('/', function(request, response) {
console.log("Got response: " + response.statusCode);
response.on('data', function(chunk) {
queryResponse+=chunk;
console.log('data');
});
response.on('end', function(){
console.log('end');
});
});
When I send the string, it shows that I got a 200 response, but those other two methods never run. Why is that?
I think you're conflating the use of the response object with that of the request.
The response object is for sending the HTTP response back to the calling client, whereas you are wanting to access the body of the request. See this answer which provides some guidance.
If you are using valid JSON and are POSTing it with Content-Type: application/json, then you can use the bodyParser middleware to parse the request body and place the result in request.body of your route.
Update for Express 4.16+
Starting with release 4.16.0, a new express.json() middleware is available.
var express = require('express');
var app = express();
app.use(express.json());
app.post('/', function(request, response){
console.log(request.body); // your JSON
response.send(request.body); // echo the result back
});
app.listen(3000);
Updated for Express 4.0 - 4.15
Body parser was split out into its own npm package after v4, requires a separate install npm install body-parser
var express = require('express')
, bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/', function(request, response){
console.log(request.body); // your JSON
response.send(request.body); // echo the result back
});
app.listen(3000);
For earlier versions of Express (< 4)
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(request, response){
console.log(request.body); // your JSON
response.send(request.body); // echo the result back
});
app.listen(3000);
Test along the lines of:
$ curl -d '{"MyKey":"My Value"}' -H "Content-Type: application/json" http://127.0.0.1:3000/
{"MyKey":"My Value"}
For Express v4+
install body-parser from the npm.
$ npm install body-parser
https://www.npmjs.org/package/body-parser#installation
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/json
app.use(bodyParser.json())
app.use(function (req, res, next) {
console.log(req.body) // populated!
next()
})
For those getting an empty object in req.body
I had forgotten to set
headers: {"Content-Type": "application/json"}
in the request. Changing it solved the problem.
#Daniel Thompson mentions that he had forgotten to add {"Content-Type": "application/json"} in the request. He was able to change the request, however, changing requests is not always possible (we are working on the server here).
In my case I needed to force content-type: text/plain to be parsed as json.
If you cannot change the content-type of the request, try using the following code:
app.use(express.json({type: '*/*'}));
Instead of using express.json() globally, I prefer to apply it only where needed, for instance in a POST request:
app.post('/mypost', express.json({type: '*/*'}), (req, res) => {
// echo json
res.json(req.body);
});
const express = require('express');
let app = express();
app.use(express.json());
This app.use(express.json) will now let you read the incoming post JSON object
Sometimes you don't need third party libraries to parse JSON from text.
Sometimes all you need it the following JS command, try it first:
const res_data = JSON.parse(body);
A beginner's mistake...i was using app.use(express.json()); in a local module instead of the main file (entry point).