Why won't my req.flash work? - json

Here's a Node.js function. It works, in the sense that bad JSON data is kicked out, but it also flashes the message that it failed. Why?
// Create document
app.post('/documents.:format?', loadUser, function(req, res) {
/////////////////////////added by adam
//tests to see if the inputed text is valid JSON data
data = req.body.d.data;
console.log("///////////" + data);
try {
type = JSON.parse(data);
console.log(type);
} catch (ex) {
console.log("bad json: "+data);
req.flash('Nope', 'Invalid JSON');
res.redirect('/documents');
return;
}
var d = new Document(req.body.d);
d.user_id = req.currentUser.id;
d.save(function() {
switch (req.params.format) {
case 'json':
res.send(d.toObject());
break;
default:
req.flash('info', 'Document created');
res.redirect('/documents');
}
});

The catch block contains both the error message and the 'bad JSON' logger, so they will always occur at the same time, due to the block scope.

Related

How to ask a confirmation before uploading a file (primeng)?

I'm trying to ask for a confirmation before upload the file so the server, currently I have this HTML code:
<p-fileUpload mode="basic" name="file" url="{{urlUpload}}" chooseLabel="Upload CSV (onBeforeSend)="onBeforeSend($event)">
Then, I have this TS code:
onBeforeSend (event): void {
const token = this.service.getTokenSession();
event.xhr.setRequestHeader('Authorization', 'Bearer ' + token);
this.confirmationService.confirm({
message: 'Are you sure to continue?',
header : 'Confirmation',
accept : () => {
this.service.showLoader();
this.onUpload(event);
},
reject: () => {}
});
}
onUpload(event): void {
this.msgsPage = [];
try {
const response = JSON.parse(event.xhr.response);
console.log(response)
if (!response.ok) {
this.errorModalService.show('There was an error');
this.flagResultLoadErrors = true;
let c = 0;
for (let msg of response.map.errors) {
c++;
this.msgsPage.push({
detail : msg,
severity: 'error',
summary : 'Error ' + c,
});
}
}
} catch (e) {
this.errorModalService.show('Unknown error');
console.log(e)
} finally {
this.service.hideLoader();
}
}
With this, I tried to block the request, but it didn't happen, what I got is that the file is sent to the server before the confirmation dialog.
Also, I'm getting this error when I tried to get the response:
SyntaxError: Unexpected end of JSON input
Hope you can help me.
You can't block from that event. It is just an event emitted from the component.
https://github.com/primefaces/primeng/blob/master/src/app/components/fileupload/fileupload.ts#L367
You will need to use the custom uploadHandler.
<p-fileUpload name="myfile[]" customUpload="true" (uploadHandler)="myUploader($event)"></p-fileUpload>
myUploader(event) {
//event.files == files to upload
}
SyntaxError: Unexpected end of JSON input
This one means the response you are getting from the xhr response is not JSON, but you are trying to parse it. Check network tab to see what the response from the server is.

cannot read the property of undefined

I am coding a server-side app in node JS and I am using a database in MySQL.
I get "TypeError: Cannot read property 'activated' of undefined"
The request I do should say "empty set" when I do it manually in the MySQL terminal.
When I try to use it in my code an I input and invalid discord_key, it returns an error, but I want it to return just a false alarm so I can catch it and use that info.
function checkKey(key) {
var activated = "";
var sqlcheck = "SELECT activated from authentification where discord_ key = ?";
console.log("in function");
DB.query(sqlcheck, [key], function (err, result) {
if (err) throw (err);
activated = result[0].activated;
});
if (!activated) {
console.log("null");
return ("NULL");
} else {
console.log("used");
return ("used");
}
}
I should get :
that request sends an empty set, so the key doesn't exist.
thank you for your help!
In case no result you can write this:
if (err) throw (err);
activated = result.length ? result[0].activated : false;
That will return false in case of no result.
The Error
The error is telling you that a variable you are using is undefined. It tells you this because you attempt to read a property from an undefined variable.
You mentioned result is an empty array. This means that any index you attempt to access returns undefined. For example:
let result = []
console.log(result[0] === undefined) // prints true
And in javascript, if you try and access a property of undefined, you get your error. Continuing our example:
result[0].activated // Throws error: Cannot read property 'activated' of undefined.
Since there is no guarentee that result[0] has a value, you should make sure it is not undefined before accessing it's properties. As #NipunChawla shows, one way is to check the array has a length (i.e at lease one value):
if (result.length) { // Does result have values?
activated = result[0].activated
} else {
activated = false
}
Better yet, if you know you are working with result[0] only, check whether it is defined directly:
if (result[0]) { // Does result[0] have a value?
activated = result[0].activated
} else {
activated = false
}
You are still left with the possibility that result[0].activated does not exist. Meaning activated would be undefined.
if (result[0] && result[0].activated) { // ... and does the first value
// contain the property activated?
activated = result[0].activated
} else {
activated = false
}
So all together now:
DB.query(sqlcheck, [key], function (err, result) {
if (err) throw (err);
if (result[0] && result[0].activated) {
activated = result[0].activated
} else {
activated = false
}
})
Async Callbacks
To fix !activated in the second if statement always being true, you should look into how callbacks work. Basically DB.query goes off and does its thing. When it is done, it will execute the function you provided it as a callback. The order of execution looks something like this:
Call DB.query to send a request to your database
Continue execution of your script. i.e check if (!activated) { ...
DB.query has now finished and calls your callback, assigning activated = result[0].activated. i.e function(err, result)
A quick way you could fix this would be like so:
function checkKey(key) {
var activated = "";
var sqlcheck = "SELECT activated from authentification where discord_ key = ?";
console.log("in function");
DB.query(sqlcheck, [key], function (err, result) {
if (err) throw (err);
if (result[0] && result[0].activated) {
activated = result[0].activated
} else {
activated = false
}
doSomethingWithResult(activated)
});
}
function doStuffWithResult(activated) {
if (!activated) {
console.log("null");
// Do your !activated stuff
} else {
console.log("used");
// Do your activated stuff
}
}
See this question for more info.

Node.js ERROR: (node:9748) UnhandledPromiseRejectionWarning: Unhandled promise rejection

I'm trying to get a json from "nightmare" in Node.js and then use JSON.parse(), but I'm getting the following error:
(node:9748) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): SyntaxError: Unexpected token ☻ in JSON at position 18509
My code:
var nightmare = Nightmare()
.goto('URL')
.wait(10000) // Need wait some time
.evaluate(() => {
return document.body.innerText;
})
.end()
.then((body) => {
var data;
try {
data = JSON.parse(body);
} catch(e) {
console.log(e);
}
callback(null, data);
});
You can check if the JSON is valid or not simply using the JSON.parse function as you are using.
function validJSON(str) {
try {
// try to parse the JSON
JSON.parse(str);
} catch (e) {
// if not a json
return false;
}
// if it's valid json
return true;
}
It'll check if the string is valid json or not. Now, you can use it with your nightmareJS.
const nightmare = Nightmare()
.goto("URL")
.wait(10000) // Need wait some time
.evaluate(() => {
return document.body.innerText;
})
.end()
.then(body => {
// if it's a valid json, send it,
// otherwise send it as a body object
const data = validJSON(body) ? body : { body };
callback(null, data);
});
Now, the error is showing because you said to catch(e) and console.log(e) the error. Thus it's simply obeying your command.
Since the emoji itself is not a valid json, you have to either make a json from it, or parse it if it was a json string.
A valid json object might look like this,
{emoji: "☻"}
You see how it's all quoted?

Unable to return JSON response to client using Node

I am having trouble returning a JSON object back to a client upon request - I am just working with the first GET call to '/btc'.
//Main server to recieve requests
http.createServer(function(req,res){
switch(req.method){
case 'GET':
switch(req.url){
case '/btc':
callBtcApi(req,res)
console.log(' btc called');
break;
case '/wallet':
callBtcWallet(req,res)
console.log('wallet called');
break;
case '/weather':
callWeather(req,res);
console.log('weather called');
break
default:
console.log('calling but not hitting');
break;
}
case 'POST':
switch(req.url){
case '/update':
console.log('update called');
break;
}
}
}).listen(3000);
callBtcApi() below, queries a bitcoin API and returns a JSON object successfully (I do intend to do more with the function, just getting the basics down first). callBtcApi() is successfully being called.
function callBtcApi(req,res){
message = '';
https.get('https://api.bitcoinaverage.com/ticker/global/GBP/', function(res){
res.on('data',function(data){
message += data;
});
res.on('end',function(){
console.log('props called ;)');
writeToCLient(res,message);
});
}).on('error', function(e){
console.error(e);
});
}
The issue I am having is when I then pass this data to my writeToCLient() function in res.on('end'). The error i receive in the terminal is
TypeError: res.setHeader is not a function
I know the message is passed into the function writeToCLient() as I am able to see the data in the terminal when I console.log(message) if I temporarurly hide all of the res.() calls.
function writeToCLient(res,message){
console.log(message);
res.statusCode = 200;
res.setHeader('Content-Type','application/json');
res.end(JSON.stringify(message));
}
I have searched google but haven't found anything that explains what could be the issue. Is the issue possibly down to calling a HTTP.get() request from inside callBtcApi() which is sitting inside my main server?
Thanks
Can you try with this?
function callBtcApi(request,response){
message = '';
https.get('https://api.bitcoinaverage.com/ticker/global/GBP/', function(res){
res.on('data',function(data){
message += data;
});
res.on('end',function(){
console.log('props called ;)');
writeToCLient(response,message);
});
}).on('error', function(e){
console.error(e);
});
}

How to pass errors conditions

In web app development I would like a consistent way to catch and report error conditions. For example, a database update routine may detect a variety of error conditions and ideally I would like the application to capture them and report gracefully. The code below din't work because retdiag is undefined when error is thrown...
function saveData(app,e) {
var db ;
var retdiag = "";
var lock = LockService.getPublicLock();
lock.waitLock(30000);
try {
// e.parameters has all the data fields from form
// re obtain the data to be updated
db = databaseLib.getDb();
var result = db.query({table: 'serviceUser',"idx":e.parameter.id});
if (result.getSize() !== 1) {
throw ("DB error - service user " + e.parameter.id);
}
//should be one & only one
retdiag = 'Save Data Finished Ok';
}
catch (ex) {
retdiag= ex.message // undefined!
}
finally {
lock.releaseLock();
return retdiag;
}
}
Is there a good or best practice for this is GAS?
To have a full error object, with message and stacktrace you have to build one, and not just throw a string. e.g. throw new Error("DB error ...");
Now, a more "consistent" way I usually implement is to wrap all my client-side calls into a function that will treat any errors for me. e.g.
function wrapper_(f,args) {
try {
return f.apply(this,args);
} catch(err) {
;//log error here or send an email to yourself, etc
throw err.message || err; //re-throw the message, so the client-side knows an error happend
}
}
//real client side called functions get wrapped like this (just examples)
function fileSelected(file,type) { return wrapper_(fileSelected_,[file,type]); }
function loadSettings(id) { return wrapper_(loadSettings_,[id]); }
function fileSelected_(file,type) {
; //do your thing
}
function loadSettings_(id) {
; //just examples
throw new Error("DB error ...");
}