express body-parser middleware puts data into the property name - javascript

I'm new to the nodeJS Express framework. I'm consuming a POST request that I sent using the following:
router.post('/', function(req, res) {
var data = Object.getOwnPropertyNames(req.body)[0];
});
I've sent this data from the client via:
$.ajax({
url: "write_to_region",
type: "POST",
data: JSON.stringify(grid)
});
where "grid" is a 2d array of values.
My express body parser is configured as follows:
app.use(bodyParser.urlencoded({limit: '50mb', extended: false }));
What is a better or more idiomatic way of doing this?
Note that the array is somewhat large (10kb) and contains only integers. Ideally, I would be minimizing the amount of data sent in the request.
Thanks!!

The problem is that you're not setting the appropriate Content-Type. Jquery's default Content-Type for POSTing data is application/x-www-form-urlencoded. So the body parser starts reading the request data, looking for an = to know when the "key" ends and the "value" starts. It never finds an = so it keeps appending to the key name.
To fix this you need to add these options in your $ajax() config:
contentType: "application/json; charset=utf-8",
dataType: "json",
and add the bodyParser.json() middleware:
app.use(bodyParser.json());

Related

Ajax call from client to server in nodejs

I am trying to make an ajax call from client to server with some data and want to access the data on the server.
Client:
$('#searchName').blur(function(){
$.ajax({
url: "/getcontact",
type:"GET",
dataType:"json",
data: {
name: "Malek"
},
contentType: "application/json",
success: function( result ) {
$( "#mob" ).value=result;
}
});
});
Server:
app.get("/getcontact",function(req,res){
console.log("===="+req.body.data+"====");
})
I am not able to get the value of name in req.body. If I console the req.body it is showing as [object Object] and when consoling req.body.data it is showing as undefined.
I have imported body-parser.
req.body is meant to hold request payload and not query strings.
You should use req.query instead, since you are making a GET request and not a POST/PUT/PATCH request.

Flask can't handle json data in ajax GET request

I try to send jQuery AJAX request to my flask server :
$.ajax({
type: 'GET',
url: '/get',
dataType: "json",
contentType:"application/json",
data: JSON.stringify({ subject : "gpu",
filter : {
ids: [2, 3]
}
}),
success: function (data) {
console.debug(data);
}
});
And then I wait for a response from the server. Server part looks like this:
#api.route('/get', methods=['GET'])
def get():
response = None
try:
data = request.get_json()
response = do_some_magic(data)
except Exception as e:
respond = {'state': 'error', 'data': e.message}
finally:
return json.dumps(respond)
So, this combination doesn't work. request has only args field = ImmutableMultiDict([('{"subject":"gpu","filter":{"ids":[2,3]}}', u'')]) and json field = None.
But when in ajax request I set type: 'GET' and in flask get method methods=['GET'], server starts to handle requests correctly.
So, it would not be a real issue, but then I tried to send a GET request with postman utility. It's request:
GET /get HTTP/1.1
Host: localhost:5000
Content-Type: application/json
cache-control: no-cache
Postman-Token: 1d94d81c-7d93-4cf6-865a-b8e3e28278c1
{
"subject": "gpu",
"filter": {
"ids": [
2,
3
]
}
}------WebKitFormBoundary7MA4YWxkTrZu0gW--
And flask code worked with methods=['GET']. So the question is, what can cause such behaviour?
From jQuery documentation
data
Type: PlainObject or String or Array
Data to be sent to the server.
It is converted to a query string, if not already a string. It's appended to the url for GET-requests. See processData option to prevent this automatic processing. Object must be Key/Value pairs. If value is an Array, jQuery serializes multiple values with same key based on the value of the traditional setting (described below).
If processData is set to false, it means that the data string is still appended to the URL, just without some processing.
This may be due to the behaviour of XMLHttpRequest.send()
send() accepts an optional parameter which lets you specify the request's body; this is primarily used for requests such as PUT. If the request method is GET or HEAD, the body parameter is ignored and the request body is set to null.

Creating routes for Ajax calls in NodeJs

let's say I have this route for my rendered HTML:
app.get('/profile/:id', function (req, res) { // my route
res.render('profile', { id: Number(req.params.id) }); // render the file and set a variable
});
and in my client side javascript file for the profile page I want to get data from the server. I request the data when loading the page by sending a user id to the server and the server returns a user object:
$(document).ready(function() {
var user = null;
$.ajax({
type: 'GET',
url: '', // This one is missing here
dataType: 'json'
}).done(function(data){
user = JSON.stringify(data);
});
console.log(user.name);
});
And my server would handle this function:
app.get('', function (req, res) { // missing route
var userId = ; // This is missing
var userObj = getUserById(userId);
res.send(userObj);
});
What route do I have to use? Tutorials say I have to pass in the route like /profile/:id but this route already exists?
I tried defining a new route like:
app.get('/reqUser/:id', function (req, res) { // Ajax route
res.send(getUserById(Number(req.params.id)));
});
and for my Ajax call I pass in the url http://localhost:8888/reqUser/12345 but this seems to be wrong because user is still null after using the Ajax call.
So how can I define a route handling the page and the Ajax call?
Edit: First off, you'll want to fix the bug in your client-side JS, where you are attempting to print user.name before user has been fetched from the server. You can fix this by moving your console.log statement into the done() callback like so:
$(document).ready(function() {
var user = null;
$.ajax({
type: 'GET',
url: '', // This one is missing here
dataType: 'json'
}).done(function(data){
user = JSON.stringify(data);
console.log(user.name); // log here
});
});
Regarding your routes question, you have several options. Below are two common solutions to this problem:
Create a separate api route to distinguish your API requests from your page requests. For example, app.get('/api/profile/:id, (req, res) => {...});'
Add a URL parameter to your AJAX calls specifying the format you want the response to be in, with the default being the page's HTML. For example, your AJAX would send a GET request to the URL /profile/2012?format=json, which would return the profile's information in JSON.
Personally, I prefer the first option, as it makes intent more clear.

Sending form JSON data to server via AJAX

I want to manually send my form data in JSON format to the server.
I changed my form data to a JSON fomat below.
The data I have in my clients-side javascript is in JSON (ie{"firstname":"john","lastname":"smith"}
$.ajax({
type: 'POST',
url: "http://localhost:3000/UserRegistration",
dataType: 'application/json',
data: JSONData,
success: function(data) {
}
});
I am using body-parser and in my server.js code, I do console.log(req.body) but the data is shown in this format
{ '{"firstname":"john","lastname":"smith"}': '' }
It added more curly braces. Why is that? How can i access the data in the server side
You can just serialize the form and bodyparser will parse it into json for you.
$.post('http://localhost:3000/UserRegistration', form.serialize(), function(data) {
...
});
dataType: 'application/json' will expect json response from server
Set processData : false and contentType : 'application/json'[Ref]
processData: By default, data passed in to the data option as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option to false
contentType: When sending data to the server, use this content type. Default is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases. If you explicitly pass in a content-type to $.ajax(), then it is always sent to the server (even if no data is sent)
Please directly parsed your object to json. for example: JSON.Stringfy(obj)

jQuery + node.js express POST request

I'm trying to send a post request to a node server.
This is my client-side code:
function send(userid,message){
$.ajax({
method: "POST",
url: "/chat/messages?id="+userid+'&message='+message
})
clear();
}
This is my server side code:
app.post('/chat/messages',function (req,res){
var query = url.parse(req.url,true).query
insertMessage(query.id,query.message)
})
This works, however I'm not sure getting data in the query string using post is the right way to go.
I tried adding a data field in $ajax parameter:
function send(userid,message){
$.ajax({
method: "POST",
url: "/chat/messages"
data : {'id' : userid, 'message' : message}
})
clear();
}
And using bodyParser() in the server end to parse the body contents:
app.use(bodyParser.json())
app.post('/chat/messages',function (req,res){
console.log(req.body)
})
but when I log the response, the body{ } object is always empty.
Why is that?
Is a <form> tag necessary for POST requests?
I tried editing my ajax request to use json as the dataType and stringifying the data, but the req.body is still empty.
$.ajax({
method: "POST",
url: "/chat/messages",
data : JSON.stringify({'id' : userid, 'message' : message}),
dataType: 'json',
})
When you post data to a server, the data is usually urlencoded and added to the body of the request. In your example, it would look like this:
id=<userid>&message=<message>
Therefore, the bodyparser you need to be able to parse that is bodyparser.urlencoded()
app.use(bodyParser.urlencoded())
Note that it isn't always urlencoded, it all depends on what you are using to send the post. AngularJS for example defaults to sending it as json instead. The good news is you could simply add both bodyparsers and your route won't need to know which method was used since in both cases the data would end up on req.body with key/value pairs.
You should read the express documentation. http://expressjs.com/api.html#req
// For regular html form data
app.use(bodyParser.urlencoded())
app.post('/chat/messages',function (req,res){
console.log(req.body);
console.log(req.query.id);
console.log(req.query.messages);
})
You can also do req.params
app.post('/chat/messages/:id',function (req,res){
console.log(req.body);
console.log(req.query);
console.log(req.params.id)
})

Categories