Receive empty object in node js express request - node.js

I have a problem when i upload image from react native to node js server, this is my code
Client
var url = "http://192.168.55.120:3000/uploadimg";
var file = this.state.imgsrc.uri;
const data = new FormData();
data.append('token', 'testName');
data.append('photo', {
uri: file,
type: 'image/jpeg',
name: 'testPhotoName'
});
fetch(url, {
method: 'post',
headers: {
'Accept': 'application/json, application/xml, text/plain, text/html, *.*',
'Content-Type': 'multipart/form-data'
},
body: data
}).then(res => {
console.log(res)
});
and my server code
const express = require('express'),
bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/uploadimg', function (req, res) {
console.log(req.body); // =====> empty object
})
My code is wrong ?

As you can check in body-parser docs, this package doesn't handle multipart form data bodies.
This does not handle multipart bodies, due to their complex and
typically large nature. For multipart bodies, you may be interested in
the following modules:
busboy and connect-busboy
multiparty and connect-multiparty
formidable
multer
Also, you shouldn't need to specify the content type header in fetch; it'll handle it for you depending on the provided body.

You cannot stringify the formData as mentioned in their docs
Using the FormData API is the simplest and fastest, but has the disadvantage that data collected can not be stringified.
If you want to stringify a submitted data, use the pure-AJAX method.
You may consider trying it with util-inspect

Related

ajax requests to Node.js

In my app.js file in Node.js I have this:
app.use(express.json());
which I thought was good enough but whenever I submit data via jQuery/Ajax the response is an empty object.
After doing the below however, it now get the data from req.body. But, I thought that in the newer versions of Express it was not necessary to do this anymore?
const bodyParser = require("body-parser");
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
The Ajax request:
$.ajax({
url: 'http://localhost:8000/api/v1/endpoint',
method: 'POST',
data: {key: key}
})
.done(function(data) {
console.log(data)
})
.fail(function(data) {
console.log(data);
})
The issue is with how you're making your ajax requests. express.json expects the Content-Type of the request to be JSON and I believe if you check your network call on the browser DevTools you'll see that the Content-Type of your request is not JSON.
You need to set the headers in your ajax request and also send valid JSON data like so
headers: {
'Content-Type': 'application/json',
},
data: JSON.stringify({key: key})
Then the express.json middleware will handle the request and you won't need to use the bodyParser lines of code you're using.

Parse XML body from HTTP Push request with Express & Node.js, using body-parser-xml

I need to process a HTTP push request using Node.js express.
The request is sending the body in XML format, that's why I chose the body-parser-xml package for parsing.
My problem is, that the body isn't properly parsed – I guess because the package doesn't recognize the mime type of the transferred body.
The endpoint:
const express = require('express');
const bodyParser = require('body-parser');
require('body-parser-xml')(bodyParser);
const app = express();
const PORT = 8085;
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.xml({
limit:'25MB'
}));
app.post('/feed', function (req, res, body) {
console.log(req.headers);
console.log(req.body);
res.status(200).end();
});
The output:
{
host: 'localhost:8085',
accept: '*/*',
'x-meta-feed-type': '1',
'x-meta-feed-parameters': 'feed params',
'x-meta-default-filename': 'filename.xml',
'x-meta-mime-type': 'text/xml',
'content-length': '63'
encoding: 'UTF-8',
connection: 'Keep-Alive'
}
{
'<data id': '"1234"><name>Test</name><title>Test1234</title></data>'
}
I'm not able to change the request itself (it's external), only the Node.js endpoint.
Any idea how to process the content properly?
Thanks for your help!
The request has apparently been parsed by the
app.use(express.urlencoded({ extended: true }));
middleware, which means that it must have had Content-Type: application/x-www-form-urlencoded. Remove the two app.use lines, because they make "global" body-parsing decisions (for every request), whereas you need a special treatment only for one type of request.
If you instantiate the XML body parser with the "non-standard" (that is, wrong) type, it will parse the content as XML:
app.post('/feed',
bodyParser.xml({type: "application/x-www-form-urlencoded"}),
function (req, res) {
console.log(req.headers);
console.log(req.body);
res.status(200).end();
});

Nodejs) Body of post request seems strange

I want to send a x-www-form-urlencoded request for the server. I give a json value for it like {username: 'asd', password: '12345'}.
Angular:
...
let headers: HttpHeaders = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
this._http.post('/api/authentication', form.value, {headers: headers, observe: 'response'}).subscribe((response:HttpResponse<Object>) => {
console.log(response); // response body {'{"username":"asd","password":"12345"}' : ""}
});
...
So I get something strange from back-end and I don't really understand what to change in my implementation to make this work like the input he got.
Nodejs (express):
//server.js
...
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true}));
...
--
//api/.../authentication.js
...
router.post('/', (req, res) => {
let post = req.body;
console.log( req.body); //same strange hash: {'{"username":"asd","password":"12345"}' : ""}
res.status(201).json(req.body);
});
...
Http header application/x-www-form-urlencoded means sending a x-www-form-urlencoded request to the server, that's correct.
However, bodyParser.json
only parse request type application/json(default value).
Returns middleware that only parses json and only looks at requests where the Content-Type header matches the type option. Type defaults to application/json.
So it is not correct.
You should send application/json request.
Or you should parse it as application/x-www-form-urlencoded, then decode the content (json).

How can I read the data received in application/x-www-form-urlencoded format on Node server?

I'm receiving data on a webhook URL as a POST request. Note that the content type of this request is application/x-www-form-urlencoded.
It's a server-to-server request. And On my Node server, I simply tried to read the received data by using req.body.parameters but resulting values are "undefined"?
So how can I read the data request data? Do I need to parse the data? Do I need to install any npm module? Can you write a code snippet explaining the case?
If you are using Express.js as Node.js web application framework, then use ExpressJS body-parser.
The sample code will be like this.
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies
// With body-parser configured, now create our route. We can grab POST
// parameters using req.body.variable_name
// POST http://localhost:8080/api/books
// parameters sent with
app.post('/api/books', function(req, res) {
var book_id = req.body.id;
var bookName = req.body.token;
//Send the response back
res.send(book_id + ' ' + bookName);
});
You must tell express to handle urlencoded data, using an specific middleware.
const express = require('express');
const app = express();
app.use(express.urlencoded({
extended: true
}))
And on your route, you can get the params from the request body:
const myFunc = (req,res) => {
res.json(req.body);
}
The accepted answer uses express and the body-parser middleware for express. But if you just want to parse the payload of an application/x-www-form-urlencoded ContentType sent to your Node http server, then you could accomplish this without the extra bloat of Express.
The key thing you mentioned is the http method is POST. Consequently, with application/x-www-form-urlencoded, the params will not be encoded in the query string. Rather, the payload will be sent in the request body, using the same format as the query string:
param=value&param2=value2
In order to get the payload in the request body, we can use StringDecoder, which decodes buffer objects into strings in a manner that preserves the encoded multi-byte UTF8 characters. So we can use the on method to bind the 'data' and 'end' event to the request object, adding the characters in our buffer:
const StringDecoder = require('string_decoder').StringDecoder;
const http = require('http');
const httpServer = http.createServer((req, res) => {
const decoder = new StringDecoder('utf-8');
let buffer = '';
req.on('data', (chunk) => {
buffer += decoder.write(chunk);
});
req.on('end', () => {
buffer += decoder.end();
res.writeHead(200, 'OK', { 'Content-Type': 'text/plain'});
res.write('the response:\n\n');
res.write(buffer + '\n\n');
res.end('End of message to browser');
});
};
httpServer.listen(3000, () => console.log('Listening on port 3000') );
Express 4.16+ has implemented their own version of body-parser so you do not need to add the dependency to your project.
app.use(express.urlencoded()); //Parse URL-encoded bodies
Non-deprecated alternative to body-parser in Express.js
If you are creating a NodeJS server without a framework like Express or Restify, then you can use the NodeJS native querystring parser. The content type application/www-form-urlencoded format is the same as the querystring format, so we can reuse that built-in functionality.
Also, if you're not using a framework then you'll need to actually remember to read your body. The request will have the method, URL, and headers but not the body until you tell it to read that data. You can read up about that here: https://nodejs.org/dist/latest/docs/api/http.html
If you are using restify, it would be similar:
var server = restify.createServer()
server.listen(port, () => console.log(`${server.name} listening ${server.url}`))
server.use(restify.plugins.bodyParser()) // can parse Content-type: 'application/x-www-form-urlencoded'
server.post('/your_url', your_handler_func)

Undesired Format from body-parser Node JS

I have an android app sending me accelerometer data using the following where body is a string like {"device_name":"device1","time":123123123,"acceleration":1} :
con = (HttpURLConnection) new URL(SERVER).openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
writer = new OutputStreamWriter(con.getOutputStream());
writer.write(body);
writer.flush();
On the server side, I am using body parser like:
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended:false}));
...
app.post('/' function(req,res {
console.log(req.headers);
console.log(req.body);
When I get a post request, this is what shows up:
{ '{"device_name":"device1","time":123,"jerk":21.135843,"acceleration":1}': '' }
I would like to get the req.body in the form of {"device_name":"device1","time":123123123,"acceleration":1} is there a parameter I am missing to set this?
Thanks!
Update:
The client code is inaccessible for change to me, so it'll be much harder to change content type that's being sent. Here's the req.head log...
{ 'user-agent': '...(Linux; U; Android 4.1.2;...)',
host: '...',
connection: 'Keep-Alive',
'accept-encoding': 'gzip',
'content-type': 'application/x-www-form-urlencoded',
'content-length': '...' }
You're uploading a JSON string, but you don't instruct body-parser to handle those.
Instead of this:
app.use(bodyParser.urlencoded({extended:false}));
Use this:
app.use(bodyParser.json());
Also make sure that your request sets the Content-Type header to application/json. If that's not possible, and you're sure that the uploaded content is always going to be JSON, you can force the body parser to parse the body as JSON like this:
app.use(require('body-parser').json({ type : '*/*' }));

Resources