nodejs req.body undefined in case of ajax post requests - node.js

Strange issue and I have no explanation to that. I create ajax post request
$.ajax({
type: "POST",
url: "/like",
data: {"topic": "123123"},
success: function(dataString) {
console.log('123123');
}
});
Or like this:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", "/like", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send("fname=Henry&lname=Ford");
on server side (NodeJs) I have simple code
app.post('/like', function (req, res) {
console.log(req.body);
res.status(201).send('+1')
});
what I dont understand, is why I receive all the time undefined when I send ajax post request.

You need to use a body parser, see: nodejs.dev/learn/get-http-request-body-data-using-nodejs

Related

How to access response Body after simulating a POST request in Node.js?

I have been trying this out for a long time now.
I want to scrap contents from a subreddit that has adult contents.
But, the problem is that, you have to answer a simple question before you are given access to that page i.e. if you are 18+ or not.
I did some research on the source code and found that the solution is a simple POST request. where you need to send the parameters "over18=yes".
But my problem is that, I am not able to access the response body after the post.
Here's the code using http request in node. I have even tried it out with the node "request" module, but no help from that either.
Hoping to find someone who can help me out here.
var http = require("http");
var options = {
host: 'www.reddit.com',
port: 80,
path: '/over18?dest=http%3A%2F%2Fwww.reddit.com%2Fr%2Fnsfw&over18=yes',
method: 'POST'
};
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log('BODY: ' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('data\n');
req.write('data\n');
req.end();
And here is the code using the Node Request module
var request = require("request");
request.post({url:'http://www.reddit.com/over18?dest=http%3A%2F%2Fwww.reddit.com%2Fr%2Fnsfw', form: {over18:'yes'}}, function(err,httpResponse,body){
console.log(body);
});
the URL i am trying to access is http://www.reddit.com/r/nsfw
In short, when you click YES button, the form sends over18=yes parameter to url http://www.reddit.com/over18?dest=http%3A%2F%2Fwww.reddit.com%2Fr%2Fnsfw using POST method. Then, server responds with an 302 Redirection header, cookie with value over18=1 and finally redirects to url http://www.reddit.com/r/nsfw using GET request. THen, server just checks if youa have a cookie with needed valuse.
All what you need is to do request directly to the final url with cookies using GET method.
var request = require("request");
var target = "http://www.reddit.com/r/nsfw";
var jar = request.jar();
var cookie = request.cookie("over18=1");
cookie.domain = "reddit.com";
cookie.path = "/";
jar.setCookie(cookie, target, function(error, cookie) {
console.log(error);
console.log(cookie);
});
request({
uri: target,
method: "GET",
jar: jar
}, function(error, response, body) {
console.log(response.statusCode);
console.log(body);
});
I too ran into this while ahem doing some research.. Here's my version:
var url = 'http://www.reddit.com/r/nsfw/';
var request = require('request');
request = request.defaults({jar: true });
request.post({
followAllRedirects: true,
url: 'http://www.reddit.com/over18?dest=' + encodeURIComponent(url),
form: {uh: '', over18: 'yes', }
}, function(err, httpResponse, html) {
…
});
Also worth a try are Reddit's Node.js APIs, of which I personally liked Snoocore.

request node.js module can't send a simple POST

I send it like so :
var url = "http://localhost:9001/v1/sanger/auth/facebook/callback",
options = {body: JSON.stringify(params), 'Content-type': 'application/json'};
request.post(url, options, function (error, response, body) {
... callbacks ...
});
I am not getting the params in the route (tried body, params and query)
When I use postman (http://cl.ly/image/473e2m173M2v) I get it in the req.body
A better way to do this (I'm assuming you've initialized your params variable somewhere else):
request = require('request');
var options = {
url: "http://localhost:9001/v1/sanger/auth/facebook/callback",
method: 'POST',
body: params,
json: true
};
request(options, function (error, response, body) {
... callbacks ...
});
You're not able to get the body because when you call JSON.stringify(params), you're converting params to a string and you don't have a json object anymore. If you send the information as plain/text but tell the request that you want json, your express app cannot verify the content-type, as could check with:
request.get('Content-Type'); // returns undefined
Since you want a json object, you shouldn't do this. Just pass the json object, like in the example above.
Then, in your route code, you can do both req.body or req.param('a_param') (for a especific key of your json) to get those values.

angular $resource delete won't send body to express.js server

hye,
i am building an app with angular.js and node.js (Express.js) on the server side.
for some reason i am having a problem handling a delete request. no body is getting to the server side.
this is my angular.js resource code:
$scope.deleteProject = function(projectName){
var postData = {username: 'name', projectName: projectName};
Project.deleteProject.delete({}, postData,
function(res){
alert('Project Deleted');
},
function(err){
alert(err.data);
});
}
on the server side i have this:
var deleteProject = function(req, res){
console.log(req.body);
console.log(req.params);
if (req.body.projectName){
//do something
return res.send(200);
}
else
return res.send(400, 'no project name was specified');
}
now for some reason there is no body at all!! it is empty.
i have defined the route as app.delete.
if i change the route in node.js to post and in angular.js to save it works fine.
what am i missing here (banging my head).
thanks.
As per this stack overflow question and the $http service source code, a DELETE request using $http does not allow for data to be sent in the body of the request. The spec for a DELETE request is somewhat vague on whether or not a request body should be allowed, but Angular does not support it.
The only methods that allow for request bodies are POST, PUT, and PATCH. So the problem is not anywhere in your code, its in Angular's $http service.
My suggestion would be to use the generic $http(...) function and pass in the proper method:
$http({
method: 'DELETE',
url: '/some/url',
data: {...},
headers: {'Content-Type': 'application/json;charset=utf-8'}
})
Angular by default sends the Content-Type as text/plain for DELETE requests. Just add this to the headers:
var config = {
method: "DELETE"
url: yourUrl
data: yourData
headers: {"Content-Type": "application/json;charset=utf-8"}
};
$http(config);
If you want to add them to every single DELETE request add this to the app.config method in your main controller:
$httpProvider.defaults.headers.delete = { "Content-Type": "application/json;charset=utf-8" };
If you want to use the $resource object instead of $http you need to add hasBody and headers as follow:
delete: {
method: 'DELETE',
hasBody: true,
headers: {"Content-Type": "application/json;charset=UTF-8"}
}
Worked for me
Just ran into this problem. You'll have to use url params to send an id with delete.
in express:
app.delete('/api/user/:userId', user.remove);
and add to the url in angular:
$http({url: 'whatever/api/'+obj.id, method: 'DELETE'}) ...
The following works for me:
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8';
XMLHttpRequest is optional but useful if you are sending ajax.
https://docs.angularjs.org/api/ng/provider/$httpProvider for more information.
This worked for me.
$httpProvider.defaults.headers.delete = { "Content-Type": "application/json;charset=utf-8" };
And then
$http.delete(url, { data: data })

The node express's bodyParser can't get the parameter in the GET request

I ajax an GET request in client side:
$.ajax({
url: '/update',
type: 'get',
data: {
"key": key,
"value": value
},
success: function (data, err) {
}
})
then at the node side, I want get the parameter
var showParam = function (req, res) {
if (req.body) {
for (var key in req.body) {
console.log(key + ": " + req.body[key]);
}
res.send({status:'ok',message:'data received'});
} else {
console.log("nothing received");
res.send({status:'nok',message:'no Tweet received'});
}
}
app.get('/update', function(req, res){
showParam(req, res);
})
The shell show the body is empty and undefined.
But when I change the get to post (both at the client side and server side), everything is ok, I can get the parameter correctly.
What's problem with my code? Do I miss something?
If you are issuing a GET request, the URL parameters are not part of the body, and thus will not be parsed by the bodyParser middleware.
To access the query parameters, just reference req.query
You can access your data for get request in server-side by using req.query.key and req.query.value.
In order to get params from bodyParser you must use POST not GET. Your ajax request and server calls must both use POST.
http://expressjs.com/api.html#req.body
app.post('/update', function(req, res){
showParam(req, res);
});
$.ajax({
url: '/update',
type: 'POST',
data: {
"key": key,
"value": value
},
success: function (data, err) {
}
});
To get the GET params, use the url module and use query = url.parse(req.url, true).query. query will contain an object with the values accessible via query.foo

Express js - can't redirect

I am trying to do the following:
from client
var req = jQuery.post(
"http://www.example.com:3000"+"/dologin",
{"username" : username, "password" : password}).error(function(){
alert("an error occurred");
});
in express root
app.post('/dologin',function(req, res) {
res.redirect('http://bbc.co.uk');
});
result passed back
<p>Moved Temporarily. Redirecting to http://bbc.co.uk</p>
Seems that if I do post from jquery the redirect will not work. Does anyone know a way to force it to redirect?
Browser does not redirect the window on redirect on ajax response. Redirect the browser with javascript.
In server send the new site as content, for example.
res.contentType('application/json');
var data = JSON.stringify('http://site.example.com/')
res.header('Content-Length', data.length);
res.end(data);
In client
var req = jQuery.post(
"http://www.mysite.com:3000"+"/dologin",
{"username" : username, "password" : password}, 'json').error(function(){
alert("an error occurred");
}).success(function(data) {
window.location = data;
});
I've actually encountered the same thing when developing an app. It seems Express doesn't redirect if the method is post.
Try:
app.post('/dologin',function(req, res) {
req.method = 'get';
res.redirect('http://bbc.co.uk');
});
I'm doing something like this when using OAuth2. I have an link to one of my pages and this in turn redirects to google.
To redirect to another location the following code does the actual redirect
app.get('/GoogleRequestAuthorization.html',function(req,res) {
.
.
.
.
res.writeHead(302, {location: url});
res.end();
});
url being the address you want to redirect to.
The full function is...
I have come to a similar problem and solved it by checking the type of the request. In my case I use JSON, but it works for other POST requests as well:
var ajax = req.xhr;
if(ajax) {
res.status(401).json({'msg':'redirect','location':'/login'});
}
else {
req.method = 'get';
res.status(401).redirect('/login');
//Or if you prefer plain text
//res.status(333).send("Redirect");
}
This handles both Ajax POST and AJAX and standard GET requests.
On the client, in the Ajax respose callback:
$.ajax({
type: 'POST',
data: Msg,
url: '/some/post',
dataType: 'JSON'
}).success(function(data, textStatus, req ) {
if(data.msg==="redirect") window.location = data.location;
else {...}
}).error(function(data, textStatus, req) {
if(req=="Unauthorized") {
alert("Unauthorized!");
window.location = "/login";
} else if (data.responseJSON.msg==="redirect") window.location = data.responseJSON.location;
else {
//...
}
});
You can actually handle more statuses here, except for 302, which is automatically followed by JQuery and you get as response 200 from the page you wanted to redirect to. So I avoid sending the 302, sending 401 in my case, or any other status, for example 333, which will be handled as error.

Resources