Meteor HTTP.get error handling - javascript

I am trying to perform HTTP.get on a set of URLs asynchronously using futures.
Meteor version: 0.8.3
Platform: Windows server 2012
The code is somewhat like this:
var futures = _.map(test, function(url) {
var future = new Future();
var onComplete = future.resolver();
try{
// Make async http call
var httpGet = HTTP.get(url,{followRedirects: true},function(error, result) {
if(error)
{
apiLogger.error("%s is error",error);
onComplete(error, null);
}
else
{
if(result!=null){
//operations done here
onComplete(error, JSON.stringify(object1));
}
else {
apiLogger.error('%s - User encountered an error. URL not parsed: %s',user,url);
onComplete(error, null);
}
}
});
}
catch(e)
{
apiLogger.error('%s - URsarsed: %s - %s',user,url,result.statusCode);
onComplete(error, null);
}
return future;
});
The issue I am facing is improper error handling.
I am getting the following error on some URLs:
I20140904-17:57:38.609(-4)? Exception while invoking method 'parallelAsyncJob' E
rror: failed [404] <html><head><title>Apache Tomcat/7.0.12 - Error report</title
><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color
:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;ba
ckground-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;
color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,A
rial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial
,sans-serif;color:white;background-colo...
I20140904-17:57:38.617(-4)? at packages/underscore/underscore.js:255
I20140904-17:57:38.619(-4)? at Array.map (native)
I20140904-17:57:38.621(-4)? at Function._.map._.collect (packages/underscore
/underscore.js:123)
I20140904-17:57:38.623(-4)? at Function._.invoke (packages/underscore/unders
core.js:254)
I20140904-17:57:38.626(-4)? at Meteor.methods.parallelAsyncJob (app/server/m
ethods.js:1:9355)
I20140904-17:57:38.628(-4)? at maybeAuditArgumentChecks (packages/livedata/l
ivedata_server.js:1488)
I20140904-17:57:38.631(-4)? at packages/livedata/livedata_server.js:650
I20140904-17:57:38.632(-4)? at _.extend.withValue (packages/meteor/dynamics_
nodejs.js:37)
I20140904-17:57:38.635(-4)? at packages/livedata/livedata_server.js:649
I20140904-17:57:38.644(-4)? at _.extend.withValue (packages/meteor/dynamics_
nodejs.js:37)
I20140904-17:57:38.646(-4)? - - - - -
I20140904-17:57:38.648(-4)? at makeErrorByStatus (packages/http/httpcall_com
mon.js:12)
I20140904-17:57:38.650(-4)? at Request._callback (packages/http/httpcall_ser
ver.js:99)
I20140904-17:57:38.652(-4)? at Request.self.callback (C:\Users\Administrator
\AppData\Local\.meteor\tools\edf8981bb6\lib\node_modules\request\request.js:122:
22)
I20140904-17:57:38.655(-4)? at Request.EventEmitter.emit (events.js:98:17)
I20140904-17:57:38.657(-4)? at Request.<anonymous> (C:\Users\Administrator\A
ppData\Local\.meteor\tools\edf8981bb6\lib\node_modules\request\request.js:888:14
)
I20140904-17:57:38.660(-4)? at Request.EventEmitter.emit (events.js:117:20)
I20140904-17:57:38.662(-4)? at IncomingMessage.<anonymous> (C:\Users\Adminis
trator\AppData\Local\.meteor\tools\edf8981bb6\lib\node_modules\request\request.j
s:839:12)
I20140904-17:57:38.665(-4)? at IncomingMessage.EventEmitter.emit (events.js:
117:20)
I20140904-17:57:38.668(-4)? at _stream_readable.js:920:16
I20140904-17:57:38.669(-4)? at process._tickCallback (node.js:415:13)
Am I doing something wrong? Or is it some GET issue?
Update:
I am using futures because the final operation can only be performed after getting all the URLs.
Interesting thing, I am able to open the URL via browser, and even POSTMAN and getting 200 status. But meteor get is receiving 404.

Per your error message, you’re getting a 404 error code; some of your URLs are invalid. And you say yourself that it only happens on certain URLs.
Why is your code so complicated, with all these futures? HTTP.get() itself offers an asyncCallback, and you’re already using inline callbacks in your code, so why not just strip out all the futures stuff?
_.map(test, function(url) {
try {
// Make async http call
HTTP.get(url, {followRedirects: true}, function(error, result) {
if (error) {
if (result.statusCode == 404)
apiLogger.error('Error 404, URL not found: %s', url);
else
apiLogger.error('Error %s from %s for user %s',
result.statusCode, url, user);
return false;
} else {
if (result != null) {
// operations done here
} else {
apiLogger.error('Empty or invalid result returned from %s for user %s',
url, user);
}
return false;
}
});
} catch (error) {
return false;
}
});

Related

controlling exception thrown by external library

im trying to scrape some website , i use a service to bypass captcha using their library
here simplified version of my code
const dbc = require('./deathbycaptcha.js');
open_tab();
async function open_tab()
{
try {
const captcha = await solvecaptcha('xxxx' ,'somedomain' ) .catch(function (error) {throw new Error('caperror'); });
console.log('captcha is solved !');
}
catch(e)
{
console.log('--------ERRRO--------------------------');
console.log(e.message);
}
}
function solvecaptcha(datakey , url )
{
return new Promise(function(resoulve, reject){
const client = new dbc.HttpClient(config.captcha.username, config.captcha.password);
try
{
client.decode({extra: {type: 4, token_params: some_params}}, (captcha) => {
if (captcha) {
resoulve(captcha['text']);
else
reject('cant solve captcha!');
});
}
catch (e) {
reject('cant solve captcha!');
}
});
}
so it starts in the open_Tab function , i call solvecaptcha there and it returnes the solved captcha and its all good ... but sometimes there is a connection error in deathbycaptcha.js which will break the whole code
like if i close my internet connection and try this i get this error and the program crashes
C:\wamp64\www\domain_check\robot\DBC\deathbycaptcha.js:208
throw new Error(err.message);
^
Error: getaddrinfo ENOTFOUND api.dbcapi.me api.dbcapi.me:80
at ClientRequest.form.submit (C:\wamp64\www\domain_check\robot\DBC\deathbycaptcha.js:208:15)
at ClientRequest.emit (events.js:189:13)
at Socket.socketErrorListener (_http_client.js:392:9)
at Socket.emit (events.js:189:13)
at emitErrorNT (internal/streams/destroy.js:82:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
at process._tickCallback (internal/process/next_tick.js:63:19)
i like to be able to control this exception so it wouldn't break the whole code , but no matter how many try/catch i use to control this ... ti wouldn't work and still breaks my code
and its this line that cuzes the problem
client.decode({extra: {type: 4, token_params: some_params}}, (captcha) => {
if (captcha) {
resoulve(captcha['text']);
else
reject('cant solve captcha!');
});
even though i've wrapped it inside try/catch its no use !

Pino error log is empty, although error object contains information

I have written a small error handling function, which is invoked after an AXIOS request, like so:
try {
...
} catch (error) {
handleAxiosError(error);
}
The function is as follows:
function handleAxiosError(error) {
if (error.response !== undefined) {
logger.error(`Received a HTTP error. Status code: ${error.response.status}, Data: ${error.response.data}`);
} else if (error.request !== undefined) {
logger.error(error.request);
} else {
logger.error(error.message);
}
throw new Error(error);
}
Although an error is thrown:
(node:94324) UnhandledPromiseRejectionWarning: Error: Error: connect ECONNREFUSED 127.0.0.1:6557
at handleAxiosError (C:\pathtoapp\utils\utils.js:66:11)
Pino only saves the following to the log. I can't find the problem. Is this an async issue?
{"level":50,"time":1567435455281,"pid":94324,"hostname":"host","name":"app","res":{},"v":1}
Thanks!
When using async logging (the default for the Pino logger), the process might have exited before all of the logging has been processed.
See https://github.com/pinojs/pino/blob/HEAD/docs/asynchronous.md
You can also change the logging to be synchronous, and you won't have this problem:
const dest = pino.destination({ sync: true })

"Unhandled rejection" error in Aurelia Fetch Client

I use Aurelia Fetch Client library to fetch JSON data from the backend server by the code:
getData() {
let httpClient = new HttpClient();
return httpClient.fetch('http://localhost:9220/get-data')
.then(response => response.json())
.then(data => return data);
}
}
And the metod getData() is called from the another code by the code:
dataService.getData().then(data => {
this.data = data;
}).catch(error => {
this.backendError = true;
});
As you can see I use here a catch statement and in case of error it's called, but I also see in the console an error message that comes from the library: "vendor-bundle.js:1395 Unhandled rejection TypeError: Failed to fetch". How can I get rid it?
I'm unsure if this is a bug with the Aurelia HTTP Fetch Client, but adding a responseError interceptor should remove the Unhandled Exception warning in the console.
let http = new HttpClient();
http.configure(config => {
config.withInterceptor({
response(response) {
return response;
},
responseError(error) {
return error;
}
})
});
This error may also come from the UseDeveloperExceptionPage middleware in a .NET Core API. This middleware strips all headers from the response which create CORS issues and causes the "TypeError: Failed to fetch" error you saw. Here is an example of my solution, which is described in full here.
.NET Core Middleware
private static Task HandleExceptionAsync(HttpContext context, Exception exception)
{
var code = HttpStatusCode.InternalServerError;
var result = JsonConvert.SerializeObject(new { error = "An internal server error has occurred." });
context.Response.ContentType = "application/json";
context.Response.StatusCode = (int)code;
return context.Response.WriteAsync(result);
}
Aurelia Interceptor
responseError(response: any): Promise<Response> {
if (response instanceof Response) {
return response.json().then((serverError: ServerError) => {
// Do something with the error here.
return Promise.reject<Response>(serverError.error);
});
}
}

Node/Express route not waiting for Redis server callback

What specific changes need to be made to the code below so that the res.json(...) command is NOT sent until any open calls to the Redis client.somecommand(..) have returned?
The code below is throwing an error related to the client.hmset(uname, { ... } trying to set a response header after res.json(...) was called. When I move the return res.json() commands to right after the end of the client.exists(uname, function(err, reply) { ... } conditional block, instead of their current locations inside the block, the anonymous token value is sent to the client app instead of the generated token value. This indicates that the callbacks to the Redis server have not returned.
How do I change the code below so that the res.json( ... ) commands cannot run until the Redis server callback has been returned? Ideally, there would be some conditional to wait a certain period before sending an error message if the Redis server callback takes too long.
Redis is added to the routes.js file containing all the code below, by adding the following two lines to the top of the file:
var redis = require('redis');
var client = redis.createClient();
Here are the various calls to the Redis server in the code below:
client.exists(uname, function(err, reply) { ... }
client.hgetall(uname, function(err, object) { ... }
client.hmset(uname, { ... }
client.expire(uname, 10);
The complete code for the Node.js/Express.js API route is:
app.get('/user**', function(req, res) {
console.log("You Hit The User Route TOP");
request({
method: 'GET',
url: authServer + '/uaa/user',
json: true,
auth: {
user: null,
password: null,
sendImmediately: true,
bearer: bearerToken
}
}, function (error, response, body) {
if(error){
console.log('ERROR with user request.');
return res.sendStatus(500);
}
else {
var uname = '';var jwtUser = 'empty';var jwtJSON = { "token" : "anonymous" }
console.log(response.statusCode);
if(body['name']){
uname = body['name'];console.log('uname is: ');console.log(uname);
if(uname.length > 0) {
scopesLocal = body['oauth2Request'].scope.toString();
client.exists(uname, function(err, reply) {//Check to see if a Redis key for the user already exists
if (reply === 1) {//a redis key DOES exist
console.log('\"'+uname+'\" exists');
client.hgetall(uname, function(err, object) {//retrieve all the values in the hash/object that we just set
if(object) {
if(object["jwt"]) {
console.log('object[\"jwt\"] is: ');console.log(object["jwt"]);
jwtJSON = { "token" : object["jwt"] };
console.log('jwtJSON is: ');console.log(jwtJSON);
return res.json(jwtJSON);
}
}
});
} else {//a redis key DOES NOT exist
console.log('\"'+uname+'\" doesn\'t exist');
jwtUser = generateJwt(uname, authoritiesLocal);
client.hmset(uname, {//store a hash/object
'AccessToken': body['details'].tokenValue,
'TokenType': body['details'].tokenType,
'Authenticated': body['authenticated'],
'Principal': body['principal'],
'Scopes': scopesLocal.toString(),
'Authorities' : authoritiesLocal,
'jwt' : jwtUser
});
jwtJSON = { "token" : jwtUser };console.log('jwtJSON is: ');console.log(jwtJSON);
return res.json(jwtJSON);
}
client.expire(uname, 10);//set the key to expire in 10 seconds. use this to manage session length
});//end of Redis conditional block
console.log('jwtJSON is: ');console.log(jwtJSON);
} else { console.log('uname is empty!'); }
return res.json(jwtJSON);
}
};
});
console.log("You Hit The User Route BOTTOM");
});
The error message in the nodemon terminal is:
_http_outgoing.js:346
throw new Error('Can\'t set headers after they are sent.');
^
Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:346:11)
at ServerResponse.header (/home/user/nodejs_apps/oauth_seed_app/node_modules/express/lib/response.js:719:10)
at ServerResponse.json (/home/user/nodejs_apps/oauth_seed_app/node_modules/express/lib/response.js:247:10)
at Command.callback (/home/user/nodejs_apps/oauth_seed_app/app/routes.js:112:44)
at normal_reply (/home/user/nodejs_apps/oauth_seed_app/node_modules/redis/index.js:714:21)
at RedisClient.return_reply (/home/user/nodejs_apps/oauth_seed_app/node_modules/redis/index.js:816:9)
at JavascriptRedisParser.Parser.returnReply (/home/user/nodejs_apps/oauth_seed_app/node_modules/redis/index.js:188:18)
at JavascriptRedisParser.execute (/home/user/nodejs_apps/oauth_seed_app/node_modules/redis-parser/lib/parser.js:413:12)
at Socket.<anonymous> (/home/user/nodejs_apps/oauth_seed_app/node_modules/redis/index.js:267:27)
at emitOne (events.js:90:13)
at Socket.emit (events.js:182:7)
at readableAddChunk (_stream_readable.js:153:18)
at Socket.Readable.push (_stream_readable.js:111:10)
at TCP.onread (net.js:534:20)
I read this posting about the specific error message. And I read this other posting about how to wait for a callback. I also read this posting about Redis callbacks to Node. But I do not see how to apply the answers to either of those other postings to the Redis callback problem in the code above.
The problem was that the return res.json(jwtJSON); commands in the OP were NOT segregated into discrete if...else blocks.
The solution is:
if(something) {
//populate jwtJSON with a real JWT
return res.json(jwtJSON);
} else {
return res.json(jwtJSON);//this leaves the anonymous value
}
Doing this segregation for every nested condition in the above code got rid of the problem.

Dynamo DB getItem with node js throwing error

I am new to Javascript and DynamoDB. I am trying to perform getitem using aws-sdk for javascript in nodejs. primary index of Dynamo table Cars is "name" a string.
var AWS = require('aws-sdk');
AWS.config.region='eu-west-1';
var db = new AWS.DynamoDB();
var params = {
TableName : 'Cars',
Key : {
"name" : {
"S" : "Volkswagen Dasher"
},
}
}
db.getItem(params, function(err, data) {
if (err) {
console.log(err); // an error occurred
}
else {
console.log(data); // successful response
}
return next();
});
On running the above .js file I am getting the following error.
ubuntu#ubuntu:~/node$ node getItem.js
{}
/home/ubuntu/node_modules/aws-sdk/lib/request.js:30
throw err;
^ ReferenceError: next is not defined
at Response.<anonymous> (/home/ubuntu/node/getItem.js:21:10)
at Request.<anonymous> (/home/ubuntu/node_modules/aws-sdk/lib/request.js:353:18)
at Request.callListeners (/home/ubuntu/node_modules/aws-sdk/lib/sequential_executor.js:105:20)
at Request.emit (/home/ubuntu/node_modules/aws-sdk/lib/sequential_executor.js:77:10)
at Request.emit (/home/ubuntu/node_modules/aws-sdk/lib/request.js:595:14)
at Request.transition (/home/ubuntu/node_modules/aws-sdk/lib/request.js:21:10)
at AcceptorStateMachine.runTo (/home/ubuntu/node_modules/aws-sdk/lib/state_machine.js:14:12)
at /home/ubuntu/node_modules/aws-sdk/lib/state_machine.js:26:10
at Request.<anonymous> (/home/ubuntu/node_modules/aws-sdk/lib/request.js:37:9)
at Request.<anonymous> (/home/ubuntu/node_modules/aws-sdk/lib/request.js:597:12)
Plz help me out. Cheers!
Glad to see you're giving DynamoDB a try! I'm not really sure I understand the context of your code, but if your goal is to make a simple GetItem call, you don't need the 'return next()' statement. Given javascript's event driven nature, these callbacks are asynchronous and don't really "return" anything. Instead, you should inspect the response (data) and perform an action accordingly.
I.E.
dynamoDB.getItem(params, function(err, data) {
if (data) {
doSomethingWithItem(data.Item);
}
});
Also, if you're just starting out I would recommend taking a look at the document-js-sdk which a wrapper on top of the original SDK to allow you to use literals such as "string" instead of {S: "string"}.

Categories

Resources