How to manage request data on entry file in node js - javascript

In Node Js, on the entry file e.g. index.js, How can I get requested data either as Form-data or Form-URL-encoded or Raw JSON data in middleware?
In my project, I am handling various API request,
Few requests contain file type so requesting as form-data.
Few requests do not contain file type so requests are coming as Form-URL-encoded.
Now the main problem is before routing, I need a specific field from req.body in the middleware.
But I am getting req.body as undefined.
For reference here is my index.js file:
const express = require('express');
const app = express();
app.use(express.raw());
app.use(express.urlencoded({ extended: false }));
app.use((req, res, next) => {
const routes_handler = require('./routes/index.js')(app, express, req);
next();
})
app.listen(3000, () => {
console.log("Server running at Port " + 3000);
});
and the routes/index.js file as follows:
module.exports = function (app, express, req) {
console.log(req.body);
//I need here data of req.body for all requests type (form data, URL-encoded, raw JSON)
app.post('/', function (req, res) {
console.log("Here I can get the requested body easily", req.body)
res.send('Hello World');
});
app.post('*', function (req, res) {
res.send({
code: 0,
message: 'No Content',
status_code: 204,
data: {
error: 'API not found!'
}
});
});
}
Also, I know for file type data, POSTMAN will send the request as Form-data, not as Form-url-encoded. So which I should choose Formidable or Multer?

The way you get all the data in index.js is by creating middlewares for your application, every time any routes that go into your application will be passed through this middleware.
Middleware functions are functions that have access to the request object (req), the response object (res), and the next function in the application’s request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.
The below middleware will simply listen to all routes & adds up request time to request time, here goes the code
let express = require('express')
let app = express()
let bodyParser = require("body-parser")
app.use(bodyParser.json())
let requestTime = function (req, res, next) { // simply updating add the requestBody using the middleware
req.requestTime = Date.now();
req.json_body = req.body;
next()
}
app.use(requestTime) // requestTime is the middleware here
app.get('/', function (req, res) {
var responseText = 'Hello World!<br>'
responseText += '<small>Requested at: ' + req.requestTime + '</small>'
res.send(responseText)
})
app.listen(3000)
Few things to note here
Always add interceptor above all routes
Don't forget to add next() inside the middleware, else it will not go to the next route.
Now, coming to the second part of your question which is accessing body,formdata, etc
You can use body-parser npm module to achieve that, something like this
Starting from Express 4, body-parser comes inbuilt with it, so you can try out something
app.use(express.json());
app.use(
bodyParser.urlencoded({
extended: false
})
);
Now, the last bit, you don't need Multer for formdata, but for file upload like multipart/form-data you will need this. Both are good in their own ways, I would go for Multer.
Hope this will help you :)

I believe the body-parser module is your answer.
https://www.npmjs.com/package/body-parser
Add the following line before the routes in your index.js after installing the body-parser package.
app.use(bodyParser.json())

Related

TypeError: Cannot destructure property 'name' of 'req.body' as it is undefined [duplicate]

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).

ReactJS Axios and Node.js - Data undefined? [duplicate]

I have the following Node.js code:
var express = require('express');
var app = express.createServer(express.logger());
app.use(express.bodyParser());
app.post('/', function(request, response) {
response.write(request.body.user);
response.end();
});
Now if I POST something like:
curl -d user=Someone -H Accept:application/json --url http://localhost:5000
I get Someone as expected. Now, what if I want to get the full request body? I tried doing response.write(request.body) but Node.js throws an exception saying "first argument must be a string or Buffer" then goes to an "infinite loop" with an exception that says "Can't set headers after they are sent."; this also true even if I did var reqBody = request.body; and then writing response.write(reqBody).
What's the issue here?
Also, can I just get the raw request without using express.bodyParser()?
Starting from express v4.16 there is no need to require any additional modules, just use the built-in JSON middleware:
app.use(express.json())
Like this:
const express = require('express')
app.use(express.json()) // <==== parse request body as JSON
app.listen(8080)
app.post('/test', (req, res) => {
res.json({requestBody: req.body}) // <==== req.body will be a parsed JSON object
})
Note - body-parser, on which this depends, is already included with express.
Also don't forget to send the header Content-Type: application/json
Express 4.0 and above:
$ npm install --save body-parser
And then in your node app:
const bodyParser = require('body-parser');
app.use(bodyParser);
Express 3.0 and below:
Try passing this in your cURL call:
--header "Content-Type: application/json"
and making sure your data is in JSON format:
{"user":"someone"}
Also, you can use console.dir in your node.js code to see the data inside the object as in the following example:
var express = require('express');
var app = express.createServer();
app.use(express.bodyParser());
app.post('/', function(req, res){
console.dir(req.body);
res.send("test");
});
app.listen(3000);
This other question might also help: How to receive JSON in express node.js POST request?
If you don't want to use the bodyParser check out this other question: https://stackoverflow.com/a/9920700/446681
As of Express 4, the following code appears to do the trick.
Note that you'll need to install body-parser using npm.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.listen(8888);
app.post('/update', function(req, res) {
console.log(req.body); // the posted data
});
For 2019, you don't need to install body-parser.
You can use:
var express = require('express');
var app = express();
app.use(express.json())
app.use(express.urlencoded({extended: true}))
app.listen(8888);
app.post('/update', function(req, res) {
console.log(req.body); // the posted data
});
You should not use body-parser it is deprecated. Try this instead
const express = require('express')
const app = express()
app.use(express.json()) //Notice express.json middleware
The app.use() function is used to mount the specified middleware function(s) at the path which is being specified. It is mostly used to set up middleware for your application.
Now to access the body just do the following
app.post('/', (req, res) => {
console.log(req.body)
})
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json())
var port = 9000;
app.post('/post/data', function(req, res) {
console.log('receiving data...');
console.log('body is ',req.body);
res.send(req.body);
});
// start the server
app.listen(port);
console.log('Server started! At http://localhost:' + port);
This will help you. I assume you are sending body in json.
This can be achieved without body-parser dependency as well, listen to request:data and request:end and return the response on end of request, refer below code sample. ref:https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/#request-body
var express = require('express');
var app = express.createServer(express.logger());
app.post('/', function(request, response) {
// push the data to body
var body = [];
request.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
// on end of data, perform necessary action
body = Buffer.concat(body).toString();
response.write(request.body.user);
response.end();
});
});
In my case, I was missing to set the header:
"Content-Type: application/json"
Try this:
response.write(JSON.stringify(request.body));
That will take the object which bodyParser has created for you and turn it back into a string and write it to the response. If you want the exact request body (with the same whitespace, etc), you will need data and end listeners attached to the request before and build up the string chunk by chunk as you can see in the json parsing source code from connect.
The accepted answer only works for a body that is compatible with the JSON format. In general, the body can be accessed using
app.use(
Express.raw({
inflate: true,
limit: '50mb',
type: () => true, // this matches all content types
})
);
like posted here. The req.body has a Buffer type and can be converted into the desired format.
For example into a string via:
let body = req.body.toString()
Or into JSON via:
let body = req.body.toJSON();
If you're lazy enough to read chunks of post data.
you could simply paste below lines
to read json.
Below is for TypeScript similar can be done for JS as well.
app.ts
import bodyParser from "body-parser";
// support application/json type post data
this.app.use(bodyParser.json());
// support application/x-www-form-urlencoded post data
this.app.use(bodyParser.urlencoded({ extended: false }));
In one of your any controller which receives POST call use as shown below
userController.ts
public async POSTUser(_req: Request, _res: Response) {
try {
const onRecord = <UserModel>_req.body;
/* Your business logic */
_res.status(201).send("User Created");
}
else{
_res.status(500).send("Server error");
}
};
_req.body should be parsing you json data into your TS Model.
I'm absolutely new to JS and ES, but what seems to work for me is just this:
JSON.stringify(req.body)
Let me know if there's anything wrong with it!
Install Body Parser by below command
$ npm install --save body-parser
Configure Body Parser
const bodyParser = require('body-parser');
app.use(bodyParser);
app.use(bodyParser.json()); //Make sure u have added this line
app.use(bodyParser.urlencoded({ extended: false }));
What you claim to have "tried doing" is exactly what you wrote in the code that works "as expected" when you invoke it with curl.
The error you're getting doesn't appear to be related to any of the code you've shown us.
If you want to get the raw request, set handlers on request for the data and end events (and, of course, remove any invocations of express.bodyParser()). Note that the data events will occur in chunks, and that unless you set an encoding for the data event those chunks will be buffers, not strings.
You use the following code to log post data:
router.post("/users",function(req,res){
res.send(JSON.stringify(req.body, null, 4));
});

Express Router not showing endpoint requests

I'm new to express and I'm trying to use express.Router() in order to route to different end points. When I follow tutorials online, I can only get text to send from the root '/' and no other endpoint. As far as I can tell my code matches well with the tutorial, so I'm not seeing where something is missing.
express.js
"use strict";
const express = require('express');
const app = express();
const resources = require('../routes/resources');
const commonExpress = require('common/lib/express');
commonExpress.setup_pre(app);
app.use('/', (req, res) => {
res.send('<h1>Hey Socket.io</h1>');
});
app.use('/resources', resources)
//use /routes/resources to handle endpoints
//that start with '/resources'
commonExpress.setup_post(app);
module.exports = app;
resources.js
"use strict";
const express = require('express');
const router = express.Router();
router.use(function(req, res, next) {
console.log(req.url, "#", Date.now());
next();
});
router.route('/messages').get((req, res) => {
res.send("hi get /resources/messages")
}).post((req, res) => {
res.send("hi post /resources/messages");
});
router.route('/messages/:userId').get((req, res) => {
res.send("hi get /resources/messages " + req.params.userId);
}).put((req, res) => {
res.send("hi put /resources/messages " + req.params.userId);
})
module.exports = router;
commonExpress
const express = require('express');
const logger = require('morgan');
const utils = require('./utils');
const cookieParser = require('cookie-parser');
module.exports = {
setup_pre: app => {
app.use(logger('dev'));
app.use(express.json());
app.use(cookieParser());
app.use('/health', (req, res) => res.status(200).send());
},
setup_post: app => {
app.disable('x-powered-by');
app.use(utils.handleMezError);
app.use(utils.handleMongoError);
app.use(utils.handleUnknownError);
app.use(function (req, res, next) {
res.status(404).send();
})
}
};
These are the responses I get when I use the curl command:
tk#tk-desktop:~/messenger$ curl http://localhost:4000/
<h1>Hey Socket.io</h1>tk#tk-desktop:~/messenger$ curl http://localhost:4000/resources
<h1>Hey Socket.io</h1>tk#tk-desktop:~/messenger$ curl http://localhost:4000/resources/messages
<h1>Hey Socket.io</h1>tk#tk-desktop:~/messenger$ curl http://localhost:4000/resources/messages/:userId
Your code here:
app.use('/', (req, res) => {
res.send('<h1>Hey Socket.io</h1>');
});
grabs all possibly URLs and sends a response and does not allow any of the other request handlers to see inbound requests. Since request handlers in Express are processed in the order you register them, the only request handlers that can run before this one grabs the inbound request are the ones in commonExpress.setup_pre(app);.
Probably, you want to change that above route to:
app.get('/', (req, res) => {
res.send('<h1>Hey Socket.io</h1>');
});
So, it only responds to a GET request and so it only matches the exact / URL (see details below).
It may help you to understand a few things:
app.use() is greedy. It will match any inbound URL that starts with the path you use. So, if you have app.use('/', ...), that will match all possible URLs since all URLs start with /. As such, app.use() is usually used for middleware, that prepares a request/response, but doesn't actually send one and then calls next() to continue routing to subsequent handlers and doesn't call res.send() or any other method that sends a response. Once you've sent a response and not called next(), all routing is done for that request.
Inbound requests are processed by Express in the order the request handlers are registered. So, if you have overlapping handlers, you would generally put the more permissive handlers later and the more specific handlers earlier. If you do the reverse which is what you have here, the more permissive handlers will grab everything and the others will never get a shot.
It looks like you can either change your app.use('/', ...) to an app.get('/', ...) which will only match the exact / URL and nothing else or you can change it to be a middleware handler that doesn't send a response and does call next() to continue routing.
It also looks like you may be using app.use() in other places where app.get() is more appropriate. For example with app.use('/health', ...), app.use() will match all HTTP verbs (GET, POST, PUT, DELETE, PATCH, etc...), but if you are sending a response in your route handler, you typically want to be matching only one of those verbs. If it's a request/response type of route where the browser requests content, that would be a GET and should use app.get(), not app.use().

Passing req.body through Express middleware to routes

I'm using the body-parser npm package to parse POST data in Application/JSON format and using a few different express routers to modularize the routes I'm creating. Here's the important info in my main server.js file:
server.js
var express = require('express');
var bodyParser = require('body-parser');
app.use(bodyParser.json());
// I'm using a sessionId to identify a person in this dummy app instead of adding in authentication. So the API call is sent to http://localhost:5000/johndoe/todo
app.use('/:sessionId/todo', require('./routes/todoRoutes'));
var port = process.env.PORT || 9191;
app.listen(port, function () {
console.log('Express server listening on port ' + port);
});
todoRoutes.js:
var todoRouter = require('express').Router();
todoRouter.post('/', function (req, res) {
console.log("This is the post data:");
console.log(req.body);
});
module.exports = todoRouter;
req.body seems to be getting lost through the middleware; it logs {} to the console. However, on a whim I added the following to my bodyParsing middleware in server.js:
app.use(bodyParser.json(), function (req, res, next) {
next();
});
And now it's passing req.body through to todoRoutes.js. (It now logs {title: 'Testing'}, etc. to the console like I need it to.)
What's going on here? And what's the best way to structure this so that it works the way it's supposed to? I'm new to Express, so I admit I could be structuring this all wrong.
Ugh, nevermind. I was an idiot and found that the Content-Type Header of application/JSON got turned off in Postman (read: I must have turned it off at some point) and so the bodyParser was never being used.
Dammit.
Thanks for the help to those who responded!

How can I get the body of the postrequest in nodejs?

I am getting my head around node.js and trying to construct a post request, this is my server.js file:
module.exports = function(app) {
app.post('/api/postrequest', function(req, res) {
console.log('inside postrequest');
console.log(req.body); //this is empty????
});
// application -------------------------------------------------------------
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
};
I would like to filter data from the request so try to verify what is in req.body. The problem is it is empty : {}. To test I am using Postman to submit the request:
http://localhost:8080/api/postrequest
Using the raw format to post this json:
{"name":"Eddie"}
You will need to use a middleware like body-parser to do that. Do an npm install body-parser and require it in your app with
var bodyParser = require('body-parser');
Then use it like so
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended': 'true'}));

Categories