node.js - post response is not waiting for callback to complete - javascript

I am working on node.js http server. The Server is connected to mongodb. I am requesting a post request to the server to get documents from mongodb. But the post response is not waiting for mongodb callback to complete. And therefore I am not getting required output on the client side. How to handle this?
http.createServer(function(request, response) {
if(request.method == "POST") {
var body = '';
request.on('data', function(chunk) {
console.log(chunk.toString());
body += chunk;
});
request.on('end', function() {
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
if(err) {
console.log("We are not connected");
}
else {
var sysInfo = db.collection('sysInfo');
var jsonObj = sysInfo.find().toArray();
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end(jsonObj);
}
});
})
}
});

toArray is async, so it provides its results via callback rather than returning them.
So that part should be:
sysInfo.find().toArray(function(err, docs) {
response.writeHead(200, {'Content-Type': 'text/plain'});
response.end(docs);
});

Related

Node.JS server side script to update JSON file

I have partially written a NODE.JS file to update the JSON file with data received from the client. The post works successfully. The Get command does not. I was wondering if there's a better way to do this? I have about 6 different callback options to write for. All different. I was wondering if there's a node.JS script already done that has all of the things I need. Or if there's a different language that would make it easier.
Here's the NODE:
var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
console.log('Request received: ');
if (req.method == 'POST') {
req.on('data', function (chunk) {
fs.writeFile("comments-data.json", chunk, function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
})
});
res.end('{"msg": "success"}');
};
if (req.method == 'GET') {
req.on('data', function (chunk) {
fs.readFile('comments-data.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data);
return data;
});
});
res.end(data);
};
}).listen(8080, '127.0.0.1');
console.log('Server running at http://127.0.0.1:8080/');
Here's the AJAX call:
postComment: function(commentJSON, success, error) {
$.ajax({
type: 'post',
url: 'http://127.0.0.1:8080',
data: commentJSON,
success: function(comment) {
success(comment)
},
error: error
});
},
But there's an ajax call for all sorts of things with the jquery plugin that i'm using. I need to GET, POST, PUT, DELETE, and sometimes multiple within the call.
Here's a full list of all of the callbacks i'm using:
http://viima.github.io/jquery-comments/#link-3-6
Using express you can do this much easily.
const express = require('express');
const app = express.Router();
//POST Request
app.post('/',(req, res, next)=>{
fs.writeFile("comments-data.json", chunk, function(err) {
if(err) {
return console.log(err);
}
console.log("The file was saved!");
res.json({'status': 'Success'})
})
})
//GET Request
app.get('/',(req, res, next)=>{
fs.readFile('comments-data.json', 'utf8', function (err, data) {
if (err) throw err;
obj = JSON.parse(data);
res.json({'status': 'Success', 'data':data})
});
})
As for your question regarding writing it in a different module. That is based on the pattern adopted by you. There are various nodejs patterns available eg. Controller based or classes based. It all depends on what you find comfortable.

Node.js API returns JSON in terminal but not in browser

Having a strange problem. Been searching for answers but nothing turns up. I'm doing a node api tutorial and it returns JSON from my mongoDB database in my terminal when I perform any GET request but in my browser or postman I get nothing back, only in the terminal do I get any response. When I try a POST in postman it says it can't connect to the backend.
here is my code :
var http = require('http');
var url = require('url');
var database = require('./database');
// Generic find methods (GET)
function findAllResources(resourceName, req, res) {
database.find('OrderBase', resourceName, {}, function (err, resources) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resources));
});
};
var findResourceById = function (resourceName, id, req, res) {
database.find('OrderBase', resourceName, {'_id': id}, function (err, resource) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
});
};
// Product methods
var findAllProducts = function (req, res) {
findAllResources('Products', req, res);
};
var findProductById = function (id, req, res) {
findResourceById('Products', id, req, res);
};
// Generic insert/update methods (POST, PUT)
var insertResource = function (resourceName, resource, req, res) {
database.insert('OrderBase', resourceName, resource, function (err, resource) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
});
};
// Product methods
var insertProduct = function (product, req, res) {
insertResource('OrderBase', 'Product', product, function (err, result) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(result));
});
};
var server = http.createServer(function (req, res) {
// Break down the incoming URL into its components
var parsedURL = url.parse(req.url, true);
// determine a response based on the URL
switch (parsedURL.pathname) {
case '/api/products':
if (req.method === 'GET') {
// Find and return the product with the given id
if (parsedURL.query.id) {
findProductById(id, req, res)
}
// There is no id specified, return all products
else {
findAllProducts(req, res);
}
}
else if (req.method === 'POST') {
//Extract the data stored in the POST body
var body = '';
req.on('data', function (dataChunk) {
body += dataChunk;
});
req.on('end', function () {
// Done pulling data from the POST body.
// Turn it into JSON and proceed to store it in the database.
var postJSON = JSON.parse(body);
insertProduct(postJSON, req, res);
});
}
break;
default:
res.end('You shall not pass!');
}
});
server.listen(8080);
console.log('Up and running, ready for action!');
You have several callbacks with err as first argument but you are not treating any potential error. It means if something is going wrong, you are not catching it and returning an error. I don't know if this has anything to do with it, but as a practice (not even "best", but general practice) instead of doing this
function (err, resource) {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
}
do this
function (err, resource) {
if(err){
// do something to warn the client and stop here
}
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
}
Try that, see if you are actually running into errors before trying to output an answer.
https://nodejs.org/api/http.html#http_response_end_data_encoding_callback
The response end method not send data to response socket. Maybe you change it
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify(resource));
res.writeHead(200, {'Content-Type': 'application/json'});
res.write(JSON.stringify(resource));
res.end();
if you want socket to close to do something, you can into callback to end.
res.end(#logHandle());
var MongoClient = require('mongodb').MongoClient;
var assert = require('assert');
var connect = function (databaseName, callback) {
var url = 'mongodb://localhost:27017/' + databaseName;
MongoClient.connect(url, function (error, database) {
assert.equal(null, error);
console.log("Successfully connected to MongoDB instance!");
callback(database);
})
};
exports.find = function (databaseName, collectioName, query, callback) {
connect(databaseName, function (database) {
var collection = database.collection(collectioName);
collection.find(query).toArray(
function (err, documents) {
assert.equal(err, null);
console.log('MongoDB returned the following documents:');
console.dir(JSON.parse(JSON.stringify(documents)));
//console.dir(documents);
callback(null, documents);
}
)
database.close();
})
};
I think we are going through the same tutorial, this is my solution of 'database.js', works for me.

Get request body for post operation

I use the http module and I need to get the req.body
currently I try with the following without success .
http.createServer(function (req, res) {
console.log(req.body);
this return undfiend ,any idea why?
I send via postman some short text...
Here's a very simple without any framework (Not express way).
var http = require('http');
var querystring = require('querystring');
function processPost(request, response, callback) {
var queryData = "";
if(typeof callback !== 'function') return null;
if(request.method == 'POST') {
request.on('data', function(data) {
queryData += data;
if(queryData.length > 1e6) {
queryData = "";
response.writeHead(413, {'Content-Type': 'text/plain'}).end();
request.connection.destroy();
}
});
request.on('end', function() {
request.post = querystring.parse(queryData);
callback();
});
} else {
response.writeHead(405, {'Content-Type': 'text/plain'});
response.end();
}
}
Usage example:
http.createServer(function(request, response) {
if(request.method == 'POST') {
processPost(request, response, function() {
console.log(request.post);
// Use request.post here
response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
response.end();
});
} else {
response.writeHead(200, "OK", {'Content-Type': 'text/plain'});
response.end();
}
}).listen(8000);
express framework
In Postman of the 3 options available for content type select "X-www-form-urlencoded".
app.use(bodyParser.urlencoded())
With:
app.use(bodyParser.urlencoded({
extended: true
}));
See https://github.com/expressjs/body-parser
The 'body-parser' middleware only handles JSON and urlencoded data, not multipart
req.body is a Express feature, as far as I know... You can retrieve the request body like this with the HTTP module:
var http = require("http"),
server = http.createServer(function(req, res){
var dataChunks = [],
dataRaw,
data;
req.on("data", function(chunk){
dataChunks.push(chunk);
});
req.on("end", function(){
dataRaw = Buffer.concat(dataChunks);
data = dataRaw.toString();
// Here you can use `data`
res.end(data);
});
});
server.listen(80)

Is there a way to synchronously read the contents of HTTP request body in node.js?

So I am sending an HTTP POST request to a node.js HTTP server that's running locally. I wish to extract the JSON object from the HTTP body, and use the data it holds to do some stuff on the server side.
Here is my client app, which issues the request:
var requester = require('request');
requester.post(
'http://localhost:1337/',
{body:JSON.stringify({"someElement":"someValue"})},
function(error, response, body){
if(!error)
{
console.log(body);
}
else
{
console.log(error+response+body);
console.log(body);
}
}
);
Here's the server that is supposed to receive that request:
http.createServer(function (req, res) {
var chunk = {};
req.on('data', function (chunk) {
chunk = JSON.parse(chunk);
});
if(chunk.someElement)
{
console.log(chunk);
// do some stuff
}
else
{
// report error
}
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Done with work \n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Now the issue is, since the req.on() function that has a callback extracts the POST data asynchronously, it seems like if(chunk.someElement) clause is evaluated before that is done, and so it always goes to the else clause and I am unable to do anything at all.
Is there a simpler way to handle this issue (by simpler, I mean: not
using any other fancy libraries or modules, just pure node)?
Is there
a synchronous function that performs the same tasks as req.on() and
returns the contents of the body before I do the
if(chunk.someElement) check?
You need to wait and buffer the request and parse/use the JSON on the request's 'end' event instead because there is no guarantee that all data will be received as a single chunk:
http.createServer(function (req, res) {
var buffer = '';
req.on('data', function (chunk) {
buffer += chunk;
}).on('end', function() {
var result;
try {
result = JSON.parse(buffer);
} catch (ex) {
res.writeHead(400);
return res.end('Bad JSON');
}
if (result && result.someElement)
{
console.log(chunk);
// do some stuff
}
else
{
// report error
}
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Done with work \n');
}).setEncoding('utf8');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

request.post how get the body return? [duplicate]

This question already has an answer here:
Return results from Request.js request method?
(1 answer)
Closed 8 years ago.
I'm made a test about a external post request. So I start my app this way:
var http = require('http');
var extreq = require('./app/external-request');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
var aaa = extreq.login();
response.end(JSON.stringify(aaa));
}).listen(1337, "127.0.0.1");
And inside the "external-request.js" I have:
function login() {
request.post(url, { form: {
userid: 'myuserid',
password: '*****'
}
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
var json = JSON.parse(body);
console.log(json); // Work
return json; // Not work
}
});
}
module.exports.login = login;
My problem is, how can I get the "return json" here "var aaa = extreq.login();"?
The problem here is request.post(). It's an asynchronous method, so your login function completes and returns before your request.post() call completes. The following will show what's really going on:
function login() {
// obviously, you'll need to make sure you include whatever resources
// you need from 'external-request.js' before this
request.post(url, { form: { userid: 'myuserid', password: '*****' } },
function (error, response, body) {
if (!error && response.statusCode == 200) {
var json = JSON.parse(body);
// this will log *after* the note in your main response body
console.log('this is the second thing your code will log to the console');
console.log(json); // Work
// this return doesn't actually go anywhere, it's just lost
return json; // Not work
}
});
return { whoops: 'this is what we really return' };
}
var http = require('http');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
var aaa = extreq.login();
console.log('this is the first thing your code will log to the console');
response.end(JSON.stringify(aaa));
}).listen(1337, "127.0.0.1");
... run that, and you'll see that your code isn't executing like you expect it to.
When people mention using a callback, what they're saying is that you need to package up the functionality that you want to occur when request has finished posting the external request in a callback function, and then it can do its work when it's actually ready. Something like the following:
var http = require('http');
var extreq = require('./app/external-request.js');
http.createServer(function (request, response) {
response.writeHead(200, {'Content-Type': 'text/plain'});
extreq.login(function(aaa) {
response.end(JSON.stringify(aaa));
});
console.log('this is the first thing your code will log to the console');
}).listen(1337, "127.0.0.1");
... and then, your login function:
function login(callback) {
request.post(url, { form: { userid: 'myuserid', password: '*****' } },
function (error, response, body) {
if (!error && response.statusCode == 200) {
var json = JSON.parse(body);
// this will log *after* the note in your main response body
console.log('this is the second thing your code will log to the console');
console.log(json); // Work
// bonus points: pass in body directly, and skip stringify
callback(json);
}
});
return { whoops: 'this is what we really return' };
}

Categories

Resources