Node.js Express express.json and express.urlencoded with form submit - node.js

Express (or Connect's) bodyParser middleware is marked deprecated and users are advised to use instead:
app.use(connect.urlencoded())
app.use(connect.json())
However, when I run the an example from Node.js in Action, I use curl to fill out the form as suggested by the book:
curl -F entry[title]='Ho ho ho' -F entry[body]='santa loves you' http://abc:123#127.0.0.1:3000/api/entry
It doesn't work. req.body is not defined. Am I missing something? It works fine with bodyParser.
EDIT: SOLUTION as of Express 4
Parse json this way:
var bodyParser = require('body-parser');
...
app.use(bodyParser.json());
Parse urlencoded body this way:
app.use(bodyParser.urlencoded({extended: true}));
Then there is no deprecation warning. The extended: true (default) uses the qs module and false uses the querystring module to parse the body.
Don't use app.use(bodyParser()), that usage is now deprecated.

bodyParser is in fact the composition of three middlewares (see documentation and relevant source code): json, urlencoded and multipart:
json parses application/json request bodies
urlencoded parses x-ww-form-urlencoded request bodies
and multipart parses multipart/form-data request bodies, which is what you're interested in.
If you only specify json and urlencoded middlewares, the form data won't be parsed by any middleware, thus req.body won't be defined. You then need to add a middleware that is able to parse form data such as formidable, busboy or multiparty (as stated in connect's documentation).
Here is an example, using multiparty:
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
app.use('/url/that/accepts/form-data', multipartMiddleware);
app.post('/url/that/accepts/form-data', function(req, resp) {
console.log(req.body, req.files);
});
Don't forget that by using such middlewares you allow anyone to upload files to your server: it then your responsibility to handle (and delete) those files.

Related

Cannot access to POST form's req.body with express server [duplicate]

Here is my simple form:
<form id="loginformA" action="userlogin" method="post">
<div>
<label for="email">Email: </label>
<input type="text" id="email" name="email"></input>
</div>
<input type="submit" value="Submit"></input>
</form>
Here is my Express.js/Node.js code:
app.post('/userlogin', function(sReq, sRes){
var email = sReq.query.email.;
}
I tried sReq.query.email or sReq.query['email'] or sReq.params['email'], etc. None of them work. They all return undefined.
When I change to a Get call, it works, so .. any idea?
Things have changed once again starting Express 4.16.0, you can now use express.json() and express.urlencoded() just like in Express 3.0.
This was different starting Express 4.0 to 4.15:
$ 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
}));
The rest is like in Express 3.0:
Firstly you need to add some middleware to parse the post data of the body.
Add one or both of the following lines of code:
app.use(express.json()); // to support JSON-encoded bodies
app.use(express.urlencoded()); // to support URL-encoded bodies
Then, in your handler, use the req.body object:
// assuming POST: name=foo&color=red <-- URL encoding
//
// or POST: {"name":"foo","color":"red"} <-- JSON encoding
app.post('/test-page', function(req, res) {
var name = req.body.name,
color = req.body.color;
// ...
});
Note that the use of express.bodyParser() is not recommended.
app.use(express.bodyParser());
...is equivalent to:
app.use(express.json());
app.use(express.urlencoded());
app.use(express.multipart());
Security concerns exist with express.multipart(), and so it is better to explicitly add support for the specific encoding type(s) you require. If you do need multipart encoding (to support uploading files for example) then you should read this.
Security concern using express.bodyParser()
While all the other answers currently recommend using the express.bodyParser() middleware, this is actually a wrapper around the express.json(), express.urlencoded(), and express.multipart() middlewares (http://expressjs.com/api.html#bodyParser). The parsing of form request bodies is done by the express.urlencoded() middleware and is all that you need to expose your form data on req.body object.
Due to a security concern with how express.multipart()/connect.multipart() creates temporary files for all uploaded files (and are not garbage collected), it is now recommended not to use the express.bodyParser() wrapper but instead use only the middlewares you need.
Note: connect.bodyParser() will soon be updated to only include urlencoded and json when Connect 3.0 is released (which Express extends).
So in short, instead of ...
app.use(express.bodyParser());
...you should use
app.use(express.urlencoded());
app.use(express.json()); // if needed
and if/when you need to handle multipart forms (file uploads), use a third party library or middleware such as multiparty, busboy, dicer, etc.
Note: this answer is for Express 2. See here for Express 3.
If you're using connect/express, you should use the bodyParser middleware: It's described in the Expressjs guide.
// example using express.js:
var express = require('express')
, app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(req, res){
var email = req.param('email', null); // second parameter is default
});
Here's the original connect-only version:
// example using just connect
var connect = require('connect');
var url = require('url');
var qs = require('qs');
var server = connect(
connect.bodyParser(),
connect.router(function(app) {
app.post('/userlogin', function(req, res) {
// the bodyParser puts the parsed request in req.body.
var parsedUrl = qs.parse(url.parse(req.url).query);
var email = parsedUrl.email || req.body.email;;
});
})
);
Both the querystring and body are parsed using Rails-style parameter handling (qs) rather than the low-level querystring library. In order to parse repeated parameters with qs, the parameter needs to have brackets: name[]=val1&name[]=val2. It also supports nested maps. In addition to parsing HTML form submissions, the bodyParser can parse JSON requests automatically.
Edit: I read up on express.js and modified my answer to be more natural to users of Express.
This will do it if you want to build the posted query without middleware:
app.post("/register/",function(req,res){
var bodyStr = '';
req.on("data",function(chunk){
bodyStr += chunk.toString();
});
req.on("end",function(){
res.send(bodyStr);
});
});
That will send this to the browser
email=emailval&password1=pass1val&password2=pass2val
It's probably better to use middleware though so you don't have to write this over and over in each route.
Note for Express 4 users:
If you try and put app.use(express.bodyParser()); into your app, you'll get the following error when you try to start your Express server:
Error: Most middleware (like bodyParser) is no longer bundled with Express and must be installed separately. Please see https://github.com/senchalabs/connect#middleware.
You'll have to install the package body-parser separately from npm, then use something like the following (example taken from the GitHub page):
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser());
app.use(function (req, res, next) {
console.log(req.body) // populated!
next();
})
Given some form:
<form action='/somepath' method='post'>
<input type='text' name='name'></input>
</form>
Using express
app.post('/somepath', function(req, res) {
console.log(JSON.stringify(req.body));
console.log('req.body.name', req.body['name']);
});
Output:
{"name":"x","description":"x"}
req.param.name x
Backend:
import express from 'express';
import bodyParser from 'body-parser';
const app = express();
app.use(bodyParser.json()); // add a middleware (so that express can parse request.body's json)
app.post('/api/courses', (request, response) => {
response.json(request.body);
});
Frontend:
fetch("/api/courses", {
method: 'POST',
body: JSON.stringify({ hi: 'hello' }), // convert Js object to a string
headers: new Headers({ "Content-Type": "application/json" }) // add headers
});
app.use(express.bodyParser());
Then for app.post request you can get post values via req.body.{post request variable}.
Update for Express 4.4.1
Middleware of the following is removed from Express.
bodyParser
json
urlencoded
multipart
When you use the middleware directly like you did in express 3.0. You will get the following error:
Error: Most middleware (like urlencoded) is no longer bundled with Express and
must be installed separately.
In order to utilize those middleware, now you need to do npm for each middleware separately.
Since bodyParser is marked as deprecated, so I recommend the following way using json, urlencode and multipart parser like formidable, connect-multiparty. (Multipart middleware is deprecated as well).
Also remember, just defining urlencode + json, the form data will not be parsed and req.body will be undefined. You need to define a middleware handle the multipart request.
var urlencode = require('urlencode');
var json = require('json-middleware');
var multipart = require('connect-multiparty');
var multipartMiddleware = multipart();
app.use(json);
app.use(urlencode);
app.use('/url/that/accepts/form-data', multipartMiddleware);
Update
As of Express version 4.16+, their own body-parser implementation is now included in the default Express package so there is no need for you to download another dependency.
You may have added a line to your code that looks like the following:
app.use(bodyparser.json()); //utilizes the body-parser package
If you are using Express 4.16+ you can now replace that line with:
app.use(express.json()); //Used to parse JSON bodies
This should not introduce any breaking changes into your applications since the code in express.json() is based on bodyparser.json().
If you also have the following code in your environment:
app.use(bodyParser.urlencoded({extended: true}));
You can replace that with:
app.use(express.urlencoded()); //Parse URL-encoded bodies
A final note of caution: There are still some very specific cases where body-parser might still be necessary but for the most part Express’ implementation of body-parser is all you will need for the majority of use cases.
(See the docs at expressjs/bodyparser for more details).
I was searching for this exact problem. I was following all the advice above but req.body was still returning an empty object {}. In my case, it was something just as simple as the html being incorrect.
In your form's html, make sure you use the 'name' attribute in your input tags, not just 'id'. Otherwise, nothing is parsed.
<input id='foo' type='text' value='1'/> // req = {}
<input id='foo' type='text' name='foo' value='1' /> // req = {foo:1}
My idiot mistake is your benefit.
For Express 4.1 and above
As most of the answers are using to Express, bodyParser, connect; where multipart is deprecated. There is a secure way to send post multipart objects easily.
Multer can be used as replacement for connect.multipart().
To install the package
$ npm install multer
Load it in your app:
var multer = require('multer');
And then, add it in the middleware stack along with the other form parsing middleware.
app.use(express.json());
app.use(express.urlencoded());
app.use(multer({ dest: './uploads/' }));
connect.json() handles application/json
connect.urlencoded() handles application/x-www-form-urlencoded
multer() handles multipart/form-data
You shoudn't use app.use(express.bodyParser()). BodyParser is a union of json + urlencoded + mulitpart. You shoudn't use this because multipart will be removed in connect 3.0.
To resolve that, you can do this:
app.use(express.json());
app.use(express.urlencoded());
It´s very important know that app.use(app.router) should be used after the json and urlencoded, otherwise it does not work!
Express v4.17.0
app.use(express.urlencoded( {extended: true} ))
app.post('/userlogin', (req, res) => {
console.log(req.body) // object
var email = req.body.email;
}
express.urlencoded
Demo Form
Another Answer Related
Written at Express version 4.16
Inside the router function you can use req.body property to access the post variable. For example if this was the POST route of your form, it would send back what you input:
function(req,res){
res.send(req.body);
//req.body.email would correspond with the HTML <input name="email"/>
}
P.S. for those who are familiar with PHP: In order to access PHP's $_GET variable we use req.query and to access PHP's $_POST variable we use req.body in Node.js.
Request streaming worked for me
req.on('end', function() {
var paramstring = postdata.split("&");
});
var postdata = "";
req.on('data', function(postdataChunk){
postdata += postdataChunk;
});
I could find all parameters by using following code for both POST and GET requests.
var express = require('express');
var app = express();
const util = require('util');
app.post('/', function (req, res) {
console.log("Got a POST request for the homepage");
res.send(util.inspect(req.query,false,null));
})
from official doc version 4
const express = require('express')
const app = express()
app.use(express.json());
app.use(express.urlencoded({ extended: true }))
app.post('/push/send', (request, response) => {
console.log(request.body)
})
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/',function(req,res){
res.sendfile("index.html");
});
app.post('/login',function(req,res){
var user_name=req.body.user;
var password=req.body.password;
console.log("User name = "+user_name+", password is "+password);
res.end("yes");
});
app.listen(3000,function(){
console.log("Started on PORT 3000");
})
Post Parameters can be retrieved as follows:
app.post('/api/v1/test',Testfunction);
http.createServer(app).listen(port, function(){
console.log("Express server listening on port " + port)
});
function Testfunction(request,response,next) {
console.log(request.param("val1"));
response.send('HI');
}
Use express-fileupload package:
var app = require('express')();
var http = require('http').Server(app);
const fileUpload = require('express-fileupload')
app.use(fileUpload());
app.post('/', function(req, res) {
var email = req.body.email;
res.send('<h1>Email :</h1> '+email);
});
http.listen(3000, function(){
console.log('Running Port:3000');
});
You are using req.query.post with wrong method req.query.post works with method=get, method=post works with body-parser.
Just try this by changing post to get :
<form id="loginformA" action="userlogin" method="get">
<div>
<label for="email">Email: </label>
<input type="text" id="email" name="email"></input>
</div>
<input type="submit" value="Submit"></input>
</form>
And in express code use 'app.get'
Other answers talk about the middleware to use on the server side. My answer attempt to provide developers with a simple playbook to debug the problem themselves.
In this question, the situation is:
You have a form on the client side
The data is sent by clicking on Submit button and you don't use JavaScript to send requests (so no fetch, axios, xhr,... but we can extend the solution for these cases later)
You use Express for the server side
You cannot access data in your Express code. req.body is undefined
There are some actions that you can do to find the solution by yourself:
Open the Network tab and search for your request.
Check the request header Content-Type. In this situation (form submit), the header is likely application/x-www-form-urlencoded or multipart/form-data if you send a file (with enctype="multipart/form-data" in the form tag)
Now check your Express code if you use the appropriate middleware to parse incoming requests.
If your Content-Type is application/x-www-form-urlencoded then you should have app.use(express.urlencoded({extended: true})) in your code.
If your Content-Type is multipart/form-data: because Express doesn't have a built-in middleware to parse this kind of request, you should another library for that. multer is a good one.
If you have done all the steps above, now you can access data in req.body :). If you have problems with the syntax, you should check the Express document page. The syntax could be changed because this question is posted a long time ago.
Now, we can extend this simple playbook for other cases that involve JavaScript code. The key is to check the request Content-Type. If you see application/json then you should use app.use(express.json()) in your code.
In summary, find your request Content-Type, then use the appropriate middleware to parse it.
when you are using POST method in HTML forms, you need to catch the data from req.body in the server side i.e. Node.js.
and also add
var bodyParser = require('body-parser')
app.use( bodyParser.json() );
app.use(bodyParser.urlencoded({extended: false}));
OR
use method='GET' in HTML and and catch the data by req.query in the server side i.e. Node.js

How can I replace a collection with PUT using express?

I'm trying to take a json collection of data and send it with postman or Advanced REST Client. The biggest thing I'm getting stuck with with is where the data is. I can't seem to find it in any part of the request. Note this must be done using express.
app.put('/api/', function (req, res) {
//Get data and replace table in database
res.send("RECEIVED");
});
You can use body-parser to parse the request and provide you all that submited data through request.body.data if you send you data as a form-data or request.params.data if you send your data as a query parameter.
npm install body-parser --save
And import it and use it as a middleware
var bodyParser = require("body-parser");
// some other code goes here like
// var express = require("express"):
// var app = express()
// and here attach the body-parser middleware like thiss
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
when you make a request with any Advanced REST client each key in the JSON that you pass to the request body will be accessible as request.body.key you can learn more about body-parser body-parser doc

Using body parser and dicer for multipart uploads with express js 4

I'm using express 4 with body-parser like so
var bodyParser = require('body-parser');
...
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
When I added dicer it's like body parser stops working. I no longer have any post params in req.params or req.body or req.query.
Is there a way to use body parser manually? Does body parser check for multipart forms data and just do nothing ... assume another lib will handle it?
Also, I feel I should note, that I am using dicer to parse the multipart form data for a reason and I don't want to use busboy or multer or xyz if possible.
To answer your question "Is there a way to use body-parser manually?"
the answer is yes and it is the recommended way of using it. Referring to the body-parser documentation:
express route-specific
This example demonstrates adding body parsers specifically to the routes that need them. In general, this is the most recommend way to use body-parser with express.
(I added some semi-colons because they would keep me up at night)
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) {
if (!req.body) return res.sendStatus(400);
res.send('welcome, ' + req.body.username);
})
// 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
})
So depending on which routes you need body-parser for, you can implement it with some custom middleware. Now, I have not tested this, but I'm assuming you could also implement it in the same way as other express middleware:
// URL encoded bodies
app.use('/api/url/encoded/endpoint', bodyParser.urlencoded({ extended: false }));
// JSON encoded bodies
app.use('/api/json/encoded/endpoint', bodyParser.json());
Where any routes that match the above endpoints, such as
app.use('/api/url/encoded/endpoint/test', function (req, res) { ... });
would be parsed using the appropriate middleware as long as they are below the middleware declarations in your code.
To try to answer your whole question, I would say that it would be safe to try not using either parser globally. Keep your parsers api endpoint specific and you shouldn't run into any problems.
Edit:
So your question is a little unclear. You would like to use body parser for multipart/form-data? "Body-parser does not handle multipart bodies, due to their complex and typically large nature." Again, I haven't tried it but maybe you could give the bodyParser.raw({ type: ... }) function a try if that's the case. If not, then you need to use dicer in a custom middleware function in which you check for the correct content type.

Non-deprecated alternative to body-parser in Express.js

I am going through the book Web Development with Node and Express and have hit a snag.
I was instructed to put the below in my application file, but it looks like body-parser is deprecated and will not work. How can I achieve the same functionality?
This is my current code:
app.use(require('body-parser')());
app.get('/newsletter', function(req, res){
// we will learn about CSRF later...for now, we just
// provide a dummy value
res.render('newsletter', { csrf: 'CSRF token goes here' });
});
app.post('/process', function(req, res){
console.log('Form (from querystring): ' + req.query.form);
console.log('CSRF token (from hidden form field): ' + req.body._csrf);
console.log('Name (from visible form field): ' + req.body.name);
console.log('Email (from visible form field): ' + req.body.email); res.redirect(303, '/thank-you');
});
Just wanted to update this thread because I tried the solution above and received undefined. Express 4.16+ has implemented their own version of body-parser so you do not need to add the dependency to your project. You can run it natively in express as follows:
app.use(express.json()); // Used to parse JSON bodies
app.use(express.urlencoded()); // Parse URL-encoded bodies using query-string library
// or
app.use(express.urlencoded({ extended: true })); // Parse URL-encoded bodies using qs library
Source: Express JS — body-parser and why may not need it
See also: query-string vs qs
From: bodyParser is deprecated express 4
It means that using the bodyParser() constructor has been deprecated, as of 2014-06-19.
app.use(bodyParser()); //Now deprecated
You now need to call the methods separately
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded());
app.use(bodyParser.json());
And so on.
Do not use body-parser anymore
Since Express 4.16+ the body parsing functionality has become builtin with express
So, you can simply do
app.use(express.urlencoded({extended: true}));
app.use(express.json()) // To parse the incoming requests with JSON payloads
from directly express, without having to install body-parser.
you can now uninstall body-parser using npm uninstall body-parser
And to get the POST data content, you can use req.body
app.post("/yourpath", (req, res)=>{
var postData = req.body;
//Or if body comes as string,
var postData = JSON.parse(req.body);
});

NodeJS and Express : How to print all the parameters passed in GET and POST request

I want to log all the query parameters which are passed to my endpoint. whenever they call me ie through GET , POST. i am able to print all the GET query params but struggling with POST params.
i used req.body but that doesnt work it just prints [Object object] even JSON.stringify didnt help.
Can any one point me to right source to look for it
So POST parameters arrive in the HTTP request body, and this is handled as a stream of data chunks by node.js. So the first thing you must do is make sure you assemble the stream of chunks into a complete piece of data. Then you may want to parse it as either url encoded or JSON if that's what it is. The standard middleware for this is body-parser. You set it up like they say in the README:
const express = require('express')
const bodyParser = require('body-parser')
const 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!
next()
})

Resources