I have the following code running on a node server # heroku. The trouble I am having is that the application frequently fails to create a new parse.com object on post. What is strange is that this code works 100% of the time on my local machine. running through heroku introduces the issue.
I run a heroku log trail when the application posts and it does not throw any exceptions/errors, so I'm stumped as to what to look for.
BTW - I realize this code isn't the prettiest, this is my first attempt to get a node/heroku/parse application up and running.
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
var Parse = require('parse/node').Parse;
var mime = require('mime');
var server = http.createServer(router).listen(process.env.PORT || 5000);
Parse.initialize("key", "key");
console.log("Parse initialized");
function router (req, res) {
var pathname = url.parse(req.url, true).pathname;
if (pathname.slice(0, 4) === '/api') {
apiHandler(req, res);
} else {
if (pathname[pathname.length - 1] === '/')
pathname += 'index.html';
staticFileHandler(pathname, res);
}
}
function staticFileHandler (pathname, res) {
fs.readFile(__dirname + '/public_html' + pathname, function (err, data) {
if (err) return errHandler(err, res);
console.log('[200]: ' + pathname);
res.setHeader('Content-Type', mime.lookup(path.extname(pathname)));
res.end(data);
});
}
function errHandler (err, res) {
if (err.code === 'ENOENT') {
res.statusCode = 404;
res.end('File not found!');
console.log('[404]: File not found: ' + err.path);
} else {
console.error(err);
}
}
function apiHandler (req, res) {
if (req.method === 'GET') {
//send back a list of todos
// var toDo = new Parse.Object("ToDo");
var parseQuery = new Parse.Query("ToDo");
parseQuery.find({
success: function(toDoList){
res.setHeader('Content-Type', mime.lookup('json'));
res.end(JSON.stringify(toDoList));
},
error: function(toDoList, error) {
// error is an instance of Parse.Error.
console.log('Error encountered while getting Parse objects: ' + error.message);
}
});
} else if (req.method === "POST"){
var body = "";
req.on('data', function (chunk) {
body += chunk;
});
var today = new Date();
req.on('end', function () {
var toDo = new Parse.Object("ToDo");
toDo.set('Description', body);
toDo.set('Done', false);
toDo.set('DueDate',today )
toDo.save(null, {
success: function(toDo) {
// Execute any logic that should take place after the object is saved.
console.log('New object created with objectId: ' + toDo.id);
},
error: function(toDo, error) {
// Execute any logic that should take place if the save fails.
// error is a Parse.Error with an error code and message.
console.log('Failed to create new object, with error code: ' + error.message);
}
});
});
res.end();
}
}
Related
I write API in order to client upload file. API has content-type multiple/form-data. But I don't know get values from client send to my
router.post('/upload/file', async (req, res) => {
var body = "";
try {
req.on('data', function (chunk) {
body += chunk;
});
req.on('end', function () {
console.log('body: ' + body);
var formData = new FormData(body);
console.log("=====================", formData.entries);
// var {accessTok, type, file} = req.params;
//
// if (!accessTok || !type || !file) {
res.json({
code: -1000,
message: 'Missing parameter(s). Please provide accessToken, type upload, file upload.'
});
res.end();
return null;
})
// }
}catch(err){
res.json({err: err.message});
res.end();
return;
}
I tried use FormData but not done. I get error is not function, formData.getKey('') is them same.
I am trying to execute few python script inside nodejs. The code is shown below. What I am trying to do is executing different python script inside a for loop one by one. and send the json response to client as soon as one script gets over.
var PythonShell = require('python-shell');
var express = require('express'), app = express();
app.get('/', function (req, res) {
res.setHeader('Content-Type', 'text/html');
pl_list=["test", "test2"]
for (var i=0; i<= pl_list.length-1; i++) {
output="";
var pyshell = new PythonShell('./'+pl_list[i]+'.py')
pyshell.on('message', function (message)
{console.log(message);output+=message;});
pyshell.end(function (err) {
if (err){
console.log('error occured ---- '+err);
}
else{
console.log('update finished');
res.write(JSON.stringify({"finsihed":true, "product_line":pl_list[i]}));
}
});
}
//res.end()
});
app.listen(5000, function () {
console.log('The web server is running. Please open http://localhost:5000/ in your browser.');
});
unfortunately I am getting the response as {"finsihed":true} actual output must be
{"finsihed":true, "product_line":"test"}{"finsihed":true, "product_line":"test2"}
can anybody tell me what I am doing wrong here. Thanks in advance!
The execution of your python scripts is asynchronous, so when you write the response to the client with this line, the value of i changed:
res.write(JSON.stringify({"finsihed":true, "product_line":pl_list[i]})
Just display the value of i with console.log before the above line and you will see that i equals 2 twice (due to the increment of your for-loop). And because pl_list[i] is undefined, the serialization of a JSON object removes the attribute "product_line".
If you want to "save" the value of i, you have to learn what closure is.
This code should work:
var PythonShell = require('python-shell');
var express = require('express'),
app = express();
app.get('/', function (req, res) {
res.setHeader('Content-Type', 'text/html');
var nbFinishedScripts = 0;
pl_list = ["test", "test2"]
for (var i = 0; i <= pl_list.length - 1; i++) {
output = "";
var pyshell = new PythonShell('./' + pl_list[i] + '.py')
pyshell.on('message', function (message)
{
console.log(message);
output += message;
});
// closure
(function (i) {
return function () {
pyshell.end(function (err) {
if (err) {
console.log('error occured ---- ' + err);
} else {
console.log('update finished');
res.write(JSON.stringify({
"finsihed": true,
"product_line": pl_list[i]
}));
}
nbFinishedScripts++;
// end the reponse when the number of finished scripts is equal to the number of scripts
if (nbFinishedScripts === pl_list.length) {
res.end();
}
});
};
})(i)(); // immediately invoke the function
}
});
app.listen(5000, function () {
console.log('The web server is running. Please open http://localhost:5000/ in your browser.');
});
Edit code:
var PythonShell = require('python-shell');
var express = require('express'),
app = express();
var executePythonScript = function (script) {
return new Promise(function (resolve, reject) {
var pyshell = new PythonShell('./' + script + '.py');
pyshell.end(function (err) {
if (err) {
reject(err);
} else {
resolve(script);
}
});
});
};
app.get('/', function (req, res) {
res.setHeader('Content-Type', 'text/html');
var pl_list = ["test", "test2"];
Promise
.all(pl_list.map(executePythonScript))
.then(function (scripts) {
scripts.forEach(function (script) {
res.write(JSON.stringify({
finsihed: true,
product_line: script
}));
});
res.end();
})
.catch(function (err) {
res.end();
});
});
app.listen(5000, function () {
console.log('The web server is running. Please open http://localhost:5000/ in your browser.');
});
Current post request:
app.post('/rImage', rawBody, function (req, res) {
// ---- check here, if this process is running ? ----
var data = req.rawBody;
var escapedData = data.replace(/([<>|&^])/g, "\^$1"); // Windows CMD escaping
exec('cscript /nologo C:/PS/Automation/render.vbs C:/PS/Automation/image.jsx"'+escapedData + '"',
function (error, stdout, stderr) {
console.log('stdout: ' + escapedData);
if(error !== null) {
console.log('exec error: ' + error);
}
res.send(stdout);
//request finished
});
});
How could I implement a queue system to this, so that the next request fires off when the last one is finished?
Thanks in adnvance!
There might be libraries for this. However, you could hack it like this:
var queue = [];
var active = false;
var check = function() {
if (!active && queue.length > 0) {
var f = queue.shift();
f();
}
}
app.post("..", body, function(req, res) {
queue.push(function() {
active = true;
exec("yourprogram arg1 arg2..", function() {
// this is the async callback
active = false;
check();
});
});
check();
});
Here's a fiddle that shows the functionality: https://jsfiddle.net/fc15afw5/1/
I got a problem with Multer, undefined req.files.path field
First, my Express.js route is:
routes.js
router.post('/', function(req, res, next){
// id, name, usersArray[], info, iconImg, headerImg
var dataObject = new MyMongooseDataObject();
// Receive data
dataObject.id = uuid.v4();
dataObject.name = req.body.name;
dataObject.usersArray = req.body.usersArray;
dataObject.info = req.body.info;
return someBindingWrapperToStoreTheFile.postFile(uuid.v4(), [req.files.iconImg.path.toString(), req.files.headerImg.path.toString()])
.then(function (postedFiles) {
dataObject.iconImg = postedFiles.body.payload.files[0].id;
dataObject.headerImg = postedFiles.body.payload.files[1].id;
//save dataObject after storing images and processing data
dataObject.save(function(savedDataObject){
next(success(req, 200, 'dataObject Saved ' + savedDataObject.id));
});
})
.catch(function(err){
console.log('FAILED: ', err.stack);
return next(failure(req, 500, err));
});
});
When I test my route with a separate small requestJS script, it works just fine:
HTTP rest api request test with requestJS
postDataObject.js
var request = require('request');
var fs = require('fs');
var uuid = require('uuid');
var formData = {
name: 'someName',
info: 'Some INFO and text description. ',
'usersArray[0][uuid]': uuid.v4().toString(),
'usersArray[1][uuid]': uuid.v4().toString(),
'usersArray[2][uuid]': uuid.v4().toString(),
// handle files
iconImg: fs.createReadStream('/var/tmp/img/iconImg.png'),
headerImg: fs.createReadStream('/var/tmp/img/headerImg.png')
};
request.post({url:'http://127.0.0.1:2233/api/postDataObject', formData: formData}, function (err, httpResponse, body) {
if (err) {
return console.error('failed:', err);
}
console.log('DataObject creation is successful! Server responded with:', body);
});
Now I'm writing the wrapper library for the fronted usage, when I use the same code in another context, it seems, that Multer handling req.files.headerImg.path is not working, it's undefined.
The code I use for wrapper library:
wrapper-lib.js
var request = require('request'),
URI = require('URIjs'),
fs = require('fs'),
uuid = require('uuid'),
path = require('path'),
Promise = require('bluebird'),
_ = require('lodash'),
DataObjectBindings.prototype.createDataObject = function (jsonRequestJSFormData) {
var self = this;
// this give the URL of the API to make requests to
return self.getAPIurlHelper().then(function (apiUrl) {
return new Promise(function (resolve, reject) {
request.post({url: apiUrl, form: jsonRequestJSFormData}, function (err, res, body) {
if (err) {
reject(err);
} else {
resolve({res: res, body: JSON.parse(body)});
};
}); //end of .post
}); // end of Promise
}); // end of getAPIurlHelper() function
}; // end of createDataObject function definition
And Finally I test the warpper with:
wrapper-test.js
// Instantiate Broker Client
var Wrapper = require('./wrapper-lib');
var wi; //wrapper instalnce
var ConnectApiRequestTracer = require('./connectApiRequestTracer');
var fs = require('fs');
ConnectApiRequestTracer().connect()
.then(function () {
wi = new Wrapper();
return wi.createDataObject(
uuid.v4(),
{
name: 'Some Cool Name',
info: 'Some nice description and info. ',
'usersArray[0][uuid]': uuid.v4().toString(),
'usersArray[1][uuid]': uuid.v4().toString(),
'usersArray[2][uuid]': uuid.v4().toString(),
iconImg: fs.createReadStream('/var/tmp/img/iconImg.png'),
headerImg: fs.createReadStream('/var/tmp/img/headerImg.png'),
);
})
.then(function (data) {
console.log('SUCCESS: ', data);
})
.catch(function (err) {
console.log('FAILED', err.stack);
});
When I run the test case wrapper-test.js, it throws me an error, that says the req.files.iconImg.path is undefined.
Any ideas what can be wrong?
try using :
req.file.iconImg.path
req.file.headerImg.path
instead of req.files.iconImg.path and req.files.headerImg.path
I've set up a NodeJS server which can be accessed by a client. Every once in a while it's necessary to let the server connect to a second server and feed the information retrieved back to the client.
Connecting to the second server is the easy part, but to be honest I have no idea how to send it back to the client. res.write seems to be forbidden during the connection with the second server.
The connection from the client is handled by handleGetRequest. The connection with the second server starts at http.get.
var http = require('http');
var url = require('url');
var server = http.createServer(function(req, res) {
var url_parsed = url.parse(req.url, true);
if (req.method ==='GET') {
handleGetRequest(res, url_parsed);
} else {
res.end('Method not supported');
}
});
handleGetRequest = function(res, url_parsed) {
if (url_parsed.path == '/secondary') {
var OPTIONS = {
hostname: "localhost",
port: "8900",
path: "/from_primary"
}
http.get(OPTIONS, function(secget) {
resget.on('data', function(chunk) {
// either store 'chunk' for later use or send directly
});
}).on('error', function(e) {
console.log("Error " + e.message);
});
} else {
res.writeHead(404);
}
res.end('Closed');
};
server.listen(8000);
How do I send the chunk from http.request to the client?
I thinks passing the callback to the handleGetRequest will fix this issue:
if (req.method === 'GET') {
handleGetRequest(url_parsed, function (err, response) {
if (err) {
return res.sendStatus(500);
}
res.json(response);
});
} else {
res.end('Method not supported');
}
handleGetRequest = function (url_parsed, callback) {
// OPTIONS ...
http.get(OPTIONS, function(resget) {
var data = '';
resget.on('data', function(chunk) {
data += chunk;
});
resget.on('end', function() {
callback(null, data);
});
}).on('error', function(e) {
callback(e);
});
}
Thanks to #TalgatMedetbekov for the suggestions. I managed to implement it like this:
var http = require('http');
var url = require('url');
var server = http.createServer(function(req, res) {
var url_parsed = url.parse(req.url, true);
if (req.method ==='GET') {
handleGetRequest(res, url_parsed);
} else {
res.end('Method not supported');
}
});
handleGetSecondaryRequest = function(callback, res) {
var OPTIONS = {
hostname: "localhost",
port: "8900",
path: "/from_primary"
}
var data = null;
http.get(OPTIONS, function(func, data) {
func.on('data', function(chunk) {
data += chunk;
});
func.on('end', function() {
callback(res, data);
});
}).on('error', function(e) {
callback(res, e);
})
};
var secReqCallback = function(res, recData)
{
res.write(recData);
res.end("END");
};
handleGetRequest = function(res, url_parsed) {
if (url_parsed.path == '/secondary') {
handleGetSecondaryRequest(secReqCallback, res);
} else {
res.writeHead(404);
}
};
server.listen(8000);
It works, kind of. There's an 'undefined' in front of the string which I can't find the cause for, but the basic functionality works perfect.
The callback construction is necessary to synchronize the asynchronous nature of NodeJS.