Express bodyParser not working properly - json

I have a problem with bodyparser that I can't figure out.
A few weeks ago I created a REST API with Express and used bodyParser to read JSON data from the client. Everything worked well but this morning I tried to launch my application and all my req.body.data are undefined, in fact the body is equal to {}.
Here is my configuration :
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
And then I configure my routes. I've seen that you must declare that in this order, ie bodyParser before your route and this is what I do. I thought that it was a version problem but after a few upgrades the problem is still present.
I use HttpRequester to simulate the client. Everything worked fine till this morning.
Example of data sent:
{
"username": "david",
"password": "bowie",
"email": "db#sfr.fr"
}
Then there is this code for responding:
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(logger('dev'));
app.use(expressValidator());
app.use(cookieParser());
app.use('/users', users);
then in users I just create a user:
// Creation of a user.
router.post('/create', function(req, res) {
// We check current mistakes like username or password empty.
if (!userhelper.checkCreateUserRequest(req, res)) {
return;
}
// Save the user in BDD
}
In the checkCreateUserRequest I do this:
if (req.body.username == null || req.body.password == null || req.body.email == null) {
res.status(400).json({message: "malformed request", code: 1});
return false;
}
I do other things like check if username is empty for example but I don't think it's important to paste it.
Thanks you for your responses and sorry for my bad english...

You could set the correct HTTP header if you use JSON request.
Content-Type: application/json

For anyone using Express v4.16+, body-parser is no longer needed as a third-party dependency. Express has its own built-in body parser that can be used like so:
Server.js
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({extended: false}))
In my case, initializing my app this way still resulted in an empty object (i.e. {}) being logged for req.body. I found the following packages to also be helpful
npm i cors
npm i path
And those can be used by including the following in server.js (or your respective file)
app.use(cors())
app.use(express.static(path.join(__dirname, 'public')))
You may also find it necessary to include the 'Content-Type': 'application-json' header in your fetch request from your client.

Related

How do I fix the error "Cannot read properties of undefined (reading 'create')" in Node Js + open ai api [duplicate]

I have this as configuration of my Express server
app.use(app.router);
app.use(express.cookieParser());
app.use(express.session({ secret: "keyboard cat" }));
app.set('view engine', 'ejs');
app.set("view options", { layout: true });
//Handles post requests
app.use(express.bodyParser());
//Handles put requests
app.use(express.methodOverride());
But still when I ask for req.body.something in my routes I get some error pointing out that body is undefined. Here is an example of a route that uses req.body :
app.post('/admin', function(req, res){
console.log(req.body.name);
});
I read that this problem is caused by the lack of app.use(express.bodyParser()); but as you can see I call it before the routes.
Any clue?
UPDATE July 2020
express.bodyParser() is no longer bundled as part of express. You need to install it separately before loading:
npm i body-parser
// then in your app
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// create application/json parser
var jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({ extended: false })
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
res.send('welcome, ' + req.body.username)
})
// POST /api/users gets JSON bodies
app.post('/api/users', jsonParser, function (req, res) {
// create user in req.body
})
See here for further info
original follows
You must make sure that you define all configurations BEFORE defining routes. If you do so, you can continue to use express.bodyParser().
An example is as follows:
var express = require('express'),
app = express(),
port = parseInt(process.env.PORT, 10) || 8080;
app.configure(function(){
app.use(express.bodyParser());
});
app.listen(port);
app.post("/someRoute", function(req, res) {
console.log(req.body);
res.send({ status: 'SUCCESS' });
});
Latest versions of Express (4.x) has unbundled the middleware from the core framework. If you need body parser, you need to install it separately
npm install body-parser --save
and then do this in your code
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
Express 4, has built-in body parser. No need to install separate body-parser. So below will work:
export const app = express();
app.use(express.json());
No. You need to use app.use(express.bodyParser()) before app.use(app.router). In fact, app.use(app.router) should be the last thing you call.
The Content-Type in request header is really important, especially when you post the data from curl or any other tools.
Make sure you're using some thing like application/x-www-form-urlencoded, application/json or others, it depends on your post data. Leave this field empty will confuse Express.
First make sure , you have installed npm module named 'body-parser' by calling :
npm install body-parser --save
Then make sure you have included following lines before calling routes
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
As already posted under one comment, I solved it using
app.use(require('connect').bodyParser());
instead of
app.use(express.bodyParser());
I still don't know why the simple express.bodyParser() is not working...
Add in your app.js
before the call of the Router
const app = express();
app.use(express.json());
The question is answered. But since it is quite generic and req.body undefined is a frequent error, especially for beginners, I find this is the best place to resume all that I know about the problem.
This error can be caused by the following reasons:
1. [SERVER side] [Quite often] Forget or misused parser middleware
You need to use appropriate middleware to parse the incoming requests. For example, express.json() parses request in JSON format, and express.urlencoded() parses request in urlencoded format.
const app = express();
app.use(express.urlencoded())
app.use(express.json())
You can see the full list in the express documentation page
If you can't find the right parser for your request in Express (XML, form-data...), you need to find another library for that. For example, to parse XML data, you can use this library
You should use the parser middleware before the route declaration part (I did a test to confirm this!). The middleware can be configured right after the initialization express app.
Like other answers pointed out, bodyParser is deprecated since express 4.16.0, you should use built-in middlewares like above.
2. [CLIENT side] [Rarely] Forget to send the data along with the request
Well, you need to send the data...
To verify whether the data has been sent with the request or not, open the Network tabs in the browser's devtools and search for your request.
It's rare but I saw some people trying to send data in the GET request, for GET request req.body is undefined.
3. [SERVER & CLIENT] [Quite often] Using different Content-Type
Server and client need to use the same Content-Type to understand each other. If you send requests using json format, you need to use json() middleware. If you send a request using urlencoded format, you need to use urlencoded()...
There is 1 tricky case when you try to upload a file using the form-data format. For that, you can use multer, a middleware for handling multipart/form-data.
What if you don't control the client part? I had a problem when coding the API for Instant payment notification (IPN). The general rule is to try to get information on the client part: communicate with the frontend team, go to the payment documentation page... You might need to add appropriate middleware based on the Content-Type decided by the client part.
Finally, a piece of advice for full-stack developers :)
When having a problem like this, try to use some API test software like Postman. The object is to eliminate all the noise in the client part, this will help you correctly identify the problem.
In Postman, once you have a correct result, you can use the code generation tool in the software to have corresponded code. The button </> is on the right bar. You have a lot of options in popular languages/libraries...
app.use(express.json());
It will help to solve the issue of req.body undefined
// Require body-parser (to receive post data from clients)
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
Looks like the body-parser is no longer shipped with express. We may have to install it separately.
var express = require('express')
var bodyParser = require('body-parser')
var app = express()
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
// parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }))
app.use(function (req, res, next) {
console.log(req.body) // populated!
Refer to the git page https://github.com/expressjs/body-parser for more info and examples.
In case anyone runs into the same issue I was having; I am using a url prefix like
http://example.com/api/
which was setup with router
app.use('/api', router);
and then I had the following
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
What fixed my issue was placing the bodyparser configuration above app.use('/api', router);
Final
// setup bodyparser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
//this is a fix for the prefix of example.com/api/ so we dont need to code the prefix in every route
app.use('/api', router);
Most of the time req.body is undefined due to missing JSON parser
const express = require('express');
app.use(express.json());
could be missing for the body-parser
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: true}));
and sometimes it's undefined due to cros origin so add them
const cors = require('cors');
app.use(cors())
The middleware is always used as first.
//MIDDLEWARE
app.use(bodyParser.json());
app.use(cors());
app.use(cookieParser());
before the routes.
//MY ROUTES
app.use("/api", authRoutes);
express.bodyParser() needs to be told what type of content it is that it's parsing. Therefore, you need to make sure that when you're executing a POST request, that you're including the "Content-Type" header. Otherwise, bodyParser may not know what to do with the body of your POST request.
If you're using curl to execute a POST request containing some JSON object in the body, it would look something like this:
curl -X POST -H "Content-Type: application/json" -d #your_json_file http://localhost:xxxx/someRoute
If using another method, just be sure to set that header field using whatever convention is appropriate.
Use app.use(bodyparser.json()); before routing. // .
app.use("/api", routes);
History:
Earlier versions of Express used to have a lot of middleware bundled with it. bodyParser was one of the middleware that came with it. When Express 4.0 was released they decided to remove the bundled middleware from Express and make them separate packages instead. The syntax then changed from app.use(express.json()) to app.use(bodyParser.json()) after installing the bodyParser module.
bodyParser was added back to Express in release 4.16.0, because people wanted it bundled with Express like before. That means you don't have to use bodyParser.json() anymore if you are on the latest release. You can use express.json() instead.
The release history for 4.16.0 is here for those who are interested, and the pull request is here.
Okay, back to the point,
Implementation:
All you need to add is just add,
app.use(express.json());
app.use(express.urlencoded({ extended: true}));
app.use(app.router); // Route will be at the end of parser
And remove bodyParser (in newer version of express it is not needed)
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
And Express will take care of your request. :)
Full example will looks like,
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true}));
app.post('/test-url', (req, res) => {
console.log(req.body)
return res.send("went well")
})
app.listen(3000, () => {
console.log("running on port 3000")
})
You can try adding this line of code at the top, (after your require statements):
app.use(bodyParser.urlencoded({extended: true}));
As for the reasons as to why it works, check out the docs: https://www.npmjs.com/package/body-parser#bodyparserurlencodedoptions
Firsl of all, ensure you are applying this middleware (express.urlencoded) before routes.
let app = express();
//response as Json
app.use(express.json());
//Parse x-www-form-urlencoded request into req.body
app.use(express.urlencoded({ extended: true }));
app.post('/test',(req,res)=>{
res.json(req.body);
});
The code express.urlencoded({extended:true}) only responds to x-www-form-urlencoded posts requests, so in your ajax/XMLHttpRequest/fetch, make sure you are sending the request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); header.
Thats it !
in Express 4, it's really simple
const app = express()
const p = process.env.PORT || 8082
app.use(express.json())
This occured to me today. None of above solutions work for me. But a little googling helped me to solve this issue. I'm coding for wechat 3rd party server.
Things get slightly more complicated when your node.js application requires reading streaming POST data, such as a request from a REST client. In this case, the request's property "readable" will be set to true and the POST data must be read in chunks in order to collect all content.
http://www.primaryobjects.com/CMS/Article144
Wasted a lot of time:
Depending on Content-Type in your client request
the server should have different, one of the below app.use():
app.use(bodyParser.text({ type: 'text/html' }))
app.use(bodyParser.text({ type: 'text/xml' }))
app.use(bodyParser.raw({ type: 'application/vnd.custom-type' }))
app.use(bodyParser.json({ type: 'application/*+json' }))
Source: https://www.npmjs.com/package/body-parser#bodyparsertextoptions
Example:
For me,
On Client side, I had below header:
Content-Type: "text/xml"
So, on the server side, I used:
app.use(bodyParser.text({type: 'text/xml'}));
Then, req.body worked fine.
To work, you need to app.use(app.router) after app.use(express.bodyParser()), like that:
app.use(express.bodyParser())
.use(express.methodOverride())
.use(app.router);
var bodyParser = require('body-parser');
app.use(bodyParser.json());
This saved my day.
I solved it with:
app.post('/', bodyParser.json(), (req, res) => {//we have req.body JSON
});
In my case, it was because of using body-parser after including the routes.
The correct code should be
app.use(bodyParser.urlencoded({extended:true}));
app.use(methodOverride("_method"));
app.use(indexRoutes);
app.use(userRoutes);
app.use(adminRoutes);
As I get the same problem, although I know BodyParser is no longer used
and I already used the app.use(express.json())
the problem was {FOR ME}:
I was placing
app.use(express.json())
after
app.use('api/v1/example', example) => { concerns the route }
once I reorder those two lines;
1 - app.use(express.json())
2 - app.use('api/v1/example', example)
It worked perfectly
If you are using some external tool to make the request, make sure to add the header:
Content-Type: application/json
This is also one possibility: Make Sure that you should write this code before the route in your app.js(or index.js) file.
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

Postman Bad Request Error When There Is No Syntax Error

I have been trying to send a post request to my server on Postman. But I have been getting the 400 Bad Request Error. The description of the error says "The request cannot be fulfilled due to bad syntax." However, my JSON body does not have any incorrect syntax, and other similar questions do not cover this error occurring when the syntax is correct.
This is what the headers look like:
What could possibly be the reason behind this happening?
Edit:
This is the code of the server side:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
const articleRoutes = express.Router();
const PORT = 4000;
let Article = require('./article.model');
app.use(cors());
app.use(bodyParser.json());
mongoose.connect('mongodb://127.0.0.1:27017/articles', { useNewUrlParser: true, useUnifiedTopology: true });
const connection = mongoose.connection;
connection.once('open', function() {
console.log("MongoDB database connection established successfully");
});
articleRoutes.route("/content-management-system/add").post((req, res) => {
let article = new Article(req.body);
console.log(article);
article.save()
.then(article => {
res.status(200).json({'article': 'article saved successfully'});
})
.catch(err => {
res.status(400).send('adding new article failed');
});
});
app.use('/', articleRoutes);
app.listen(PORT, function() {
console.log("Server is running on Port: " + PORT);
});
Whew, silly mistake. I found my answer eventually! The answer was in my mongoose.connect line where I put "articles" when it should be "article" after "mongodb://127.0.0.1:27017/".
From Danny's comment, I realised that the "400 Bad Request" error description was kind of misleading. It made me initially think that the problem was with the JSON body that I was sending, that is, its syntax. But this might not be the problem.
So, I checked over again if my save method was the problem that caused it to always default to the catch statement. But, this didn't seem to be the problem, too.
Eventually, I found out that the problem was something really simple. I accidentally put in "articles" instead of "article" in the mongoose.connect line.
Moral of the Story: The "400 Bad Request" error displayed on Postman may be misleading and the problem might not be with the syntax of the JSON body that you are passing in as request.
Sometimes it can be silly mistakes like putting a get request when it
should be a post request.
Other times it may be incorrect syntax in the body.
Or as described above, typo in end points.
I copied the body text from somewhere. And during the copy-paste process, something like space was added to the text. That led to the 400 error. I "beatify" my text and fixed the problem.

How to serve index.html file with Apollo Server?

I have this code in index.js:
const PORT = process.env.PORT || 5000;
server.listen(PORT).then({ url }) => {
console.log(`Server running at url: ${url}`);
});
In local development, when I went to localhost:5000 on my browser, I could test with the GraphQL playground.
Now, I just finished deploying with Heroku. When I go to my URL, I see:
GET query missing. I assume this happens because apollo is trying to open the GraphQL playground, but it is blocked in production mode.
How can I tell apollo to serve client/index.html instead?
Note: I tried putting index.html in the root directory as well, but nothing changed.
I saw in a tutorial video that the answer to this question in express is:
app.use(express.static('client'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client','index.html'));
});
I don't know how to do this in Apollo.
The standalone Apollo Server cannot be used for serving static files or exposing other endpoints. If you need this functionality, you need to use an HTTP framework like Express, Hapi or Koa and then use the appropriate Apollo Server integration.
Example using Express:
const server = new ApolloServer({ ... });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);

Node.js: How to exchange a JSON object [duplicate]

This question already has answers here:
How to access POST form fields in Express
(24 answers)
Closed 6 years ago.
My purpose is to send a JSON object from the client-side to the server. So taking into account the following details of the client:
<script>
var onClickFunct = function() {
trial1.send({
"test": $("#input_test").val(),
});
}
</script>
Where input_test is the name of my tag in the html page.
And where trial1 is implemented with the following code:
var trial1 = {
//notifica al server una nuova registrazione
send: function(data){
$.getJSON('/tst',data);
}
}
My Server can't see the object; infact if I print req.params it shows me "undefined".
app.get('/tst',function(req){
console.log(req.params);
});
My index.html reuire the following script <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
While the server require only express
Try changing:
app.get('/tst',function(req){
console.log(req.params);
});
to:
app.get('/tst',function(req){
console.log(req.query);
});
The req.params is for parameters in your routes, like:
app.get('/test/:name', function (req, res) {
console.log(req.params);
});
When you access /test/abc then the req.params.name will be "abc".
The $.getJSON() sends the data as query parameters, see:
http://api.jquery.com/jquery.getjson/
And for the query parameters you use res.query.
If it was a POST request and you wanted to access parameters passed in the request body then you would user req.body (but you would need to use a bodyParser middleware).
Remember to use GET only for reading operations, where in the query parameters you specify what you want to get or in what form, what order etc.
If you pass data to store in a database or something like that then use POST or PUT for that and pass the data in the request body (which can be JSON).
$ npm install --save body-parser
and then:
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
your endpoint should look like this:
app.post('/tst',function(req){
console.log(req.body);
});
then use Jquery Post:
$.post('/tst',data);
body parser install example taken from here:
How to retrieve POST query parameters?
hope it helps :)

while using MySql, express, angular, nodejs, will the ports be different for express and node

While looking into express + node + mysql, tutorials suggest to start express server by using node server.js (here server.js contains logic to connect to mysql db), which calls upon app.listen() and angular+node tutorials start node server using npm start.
Are they different and I have to start both?
In case, yes, do I need to use diff ports?
In case, no, how to call upon mysql db? Please give some reference or elaborate.
server.js is as follows:
var express = require("express");
var mysql = require("mysql");
var app = express();
var connection = mysql.createConnection({
host : "localhost",
user : "userid",
password : "password",
database : "sakila"
});
connection.connect(function(error){
if(error) {
console.log("Problem with MySQL"+error);
} else {
console.log("Connected with Database");
}
});
app.use(express.static(__dirname + '/bower_components/angular'));
app.get('/app/#/actors_load',function(req,res){
connection.query("SELECT * from actor",function(err,rows){
if(err) {
console.log("Problem with MySQL"+err);
} else {
res.end(JSON.stringify(rows));
}
});
});
app.listen(8000,function(){
console.log("It's Started on PORT 8000");
});
My phonecatapp has following routers:
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
when('/actors_load', {
templateUrl: 'partials/actors.html',
controller: 'ActorsCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
and controller looks like this:
phonecatControllers.controller('ActorsCtrl',function($scope, $http, $interval){
load_names();
console.log("ActorsCtrl");
/*
$interval(function(){
load_names();
},300);
*/
function load_names(){
$http.get('http://localhost:8000/actors_load').success(function(data){
console.log("kdfhg"+data);
$scope.actors=data;
});
};
});
the partials of html has a link to populate the db data as:
<div>actors</div>
npm install doesn't start a server. It is a command to install packages.
In this particular example the createServer function will accept connection on port 8000. it's taken from node.js docs.
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
As soon as the above code is executed the server is ON. express is a framework for node.js. express creates server on the top of node.js so the express configuration (along with port number) will be executed by node.js. Specified port of express server will run an instance of node.js server, that's the end of the story
To connect to mysql you can use one of the mysql packages for node e.g.:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : '< MySQL username >',
password : '< MySQL password >',
database : '<your database name>'
});
connection.connect();
In above case you are using localhost as a adress of your database.
You can find plethora of mysql packages on npm site: https://www.npmjs.com/search?q=mysql
You may also use mysql.createClient for costumised connection:
var client = mysql.createClient({
user: '??',
password: '??',
port: 8889
});
Note: remember to require your packages otherwise they just simply won't work.
After doing trial and error, I found that srever.js is on server side, angular part of the project is on client side. from angular part, only way to recieve data is using REST API. This role of providing REST API will be facilitated by server.js and hence shall be run on diff port. It means I had to call npm start as well as node server.js. Then I was facing CORS issue, which I resolved by providing
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header ("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
in server.js. NOte that to see the effect of this code, you need to start the two servers. This was really a pain point for me. I spent whole day trying various combinations in various places to resolve CORS issue. It seemed not to be working. For some reasons, I stopped the servers and restarted, it was working. After few trials, I realized that even after removing above code, it was working. So, I stopped servers again and this time it was not working, that is how I realized it.
One more thing that I was mingling the two thinking them as one project having client and server side. Any newbie, please understand that client side accesses server side as REST API, so develop them as separate module/project. Do not develop as single module/project.