Detect fail of chrome.extension.sendRequest - javascript

Hey fellow Chrome Devs, how would one go about detecting when a chrome.extension.sendRequest has failed? I tried this, and no dice:
chrome.extension.sendRequest({ /* message stuff here */ }, function(req){
if(req == null || chrome.extension.lastError == null){
alert("No response. :(");
}
});
But what happens is that the callback never even fires, which is what I half expected. Is there any way to detect when a sendRequest fails?
Thanks!

You could surround it with a try{}catch(err){} to catch any errors thrown, but an error is not thrown if there is no response, and there is also no null response.
This would have been done by design, to allow a message receiver to do it's thing. For instance, it might involve a couple of web service requests, or ajax requests that could take a while.
If you know how long it should take to respond, you should implement a timeout (it would have been nice if the sendRequest function included one)
So, you could do something like this:
var noResponse = setTimeout(100, function() {
alert('No response received within 100ms!');
});
chrome.extension.sendRequest({ /* message stuff here */ }, function(req){
clearTimeout(noResponse);
alert('I have a response!');
});

You need to change....
if(req == null || chrome.extension.lastError == null){
alert("No response. :(");
}
...to....
if(req == null){
alert("No response. :( and the error was "+chrome.extension.lastError.message);
}
As the docs say for sendRequest If an error occurs while connecting to the extension, the callback will be called with no arguments and chrome.extension.lastError will be set to the error message.
http://code.google.com/chrome/extensions/extension.html#method-sendRequest
http://code.google.com/chrome/extensions/extension.html#property-lastError

Related

Chrome extension error "Unchecked runtime.lastError: The message port closed before a response was received"

I'm trying to simply call a function in background.js from popup.js. However, I get the "Unchecked runtime.lastError: The message port closed before a response was received." error.
My initial 'Handshake' message works fine without error, but my 'AnotherMessage' gets the error above.
I am trying to follow the onMessage and sendMessage documentation found here but I might be doing something wrong.
popup.js
//works perfectly fine
chrome.runtime.sendMessage({msg:"Handshake"}, response => {
if(response.error){
console.log(response);
}
});
//Gives error message
chrome.runtime.sendMessage({msg:"AnotherMessage"}, response => {
if(response.error){
console.log(response);
}
});
The reason I want two 'sendMessage' is because I want to execute specific functions in background.js depending on certain logic.
background.js
chrome.runtime.onMessage.addListener((request,sender,sendResponse){
if(request.msg === "Handshake"){
//Do something
} else if (request.msg === "AnotherMessage") {
//Do something else
}
});
UPDATE: To add a bit of context, I basically have two forms in my extension. I want to send data on form submission to my database, so 'form-1' submission executes 'function-1', and 'form-2' submission should execute 'function-2' in background.js. I'm trying to achieve the different function executions via sendMessage and onMessage.
In the background script, if you call the sendResponse asynchronous, you have to return true from the callback function
chrome.runtime.onMessage.addListener((request,sender,sendResponse){
if (request.msg === "Handshake"){
//Do something
} else if (request.msg === "AnotherMessage") {
//Do something else
}
return true;
});

what is the xhr error event object details in this scenario?

I'm testing a simple mobile upload solution - this question is not about the actual upload - in chrome it uploads the pic in firefox the error event fires - so far so good - but now I need why it fires. The event is sent over so surely there is some error info in the object - but I check the spec on the progressevent which I kinda figured out it is sending but I still cant get a error code, description or anything to help me debug - any pointers please?
xhr.addEventListener("error", uploadFailed, false);
function uploadFailed(evt) {
alert("There was an error attempting to upload the file.");
alert(evt.error.toString()); // this is where the trouble starts
// the evt.error is undefined?
}
thnx ;-)
XMLHttpRequest objects have the status or the statusText properties that correspond to the HTTP status of the request. That might be a good starting point. Also checking the JS console and the network tab in the debugger might yield some useful information (especially with CORS issues).
Using the status property, your error handler might look somehow like this:
xhr.addEventListener('error', function ()
{
if (xhr.status >= 500)
{
alert("Something went wrong on the server!");
}
else if (xhr.status >= 400)
{
alert("Something went wrong with the request on our side!");
}
else
{
alert("No HTTP error indicated, yet the error event fired?!");
}
});

Node http.ClientRequest does not fire "error" event

I have the following javascript node.js code:
var options = {
host: "x.y.z"
,path: "/api/abc/"
,method: "GET"
};
var req = http.request(options);
req.on('response' , function(data) {
console.log("response: ",data.statusCode);
done();
});
req.on('error' , function() {
console.log("error");
done();
});
req.end();
I can't get the error event when an actual HTTP request error occurs. What am I missing ?
Preliminary findings: It would appear that the failure case "no response from server" (e.g. due to network issue) does not fire any event. So, the workaround is to create a 'timer' and trap this condition by yourself.
Try using an if / else statement instead of two independent functions.
if(response you want && response.statusCode = 200){
//logic
} else {
//console.log("error")
}
You should create your own Timeout function inside the request. In fact, I believe that after a lot of time (maybe a minute?) the request would fail. But, if you require something more earlier, you can check this thread that asks for the same thing:
How to set a timeout on a http.request() in Node?

Parse custom webhook: can I query my tables?

In a Parse custom webhook, which is of the form:
app.post('/receiveSMS', function(req, res) {
Where receiveSMS is hooked up to the Twilio api and this method is properly called (I have logs to prove it), but I'm trying to query on my tables within this method and it doesn't seem to be working.
Is this allowed, or is there anything special I need to do to make this work?
var contactObj = Parse.Object.extend("Contact");
var contactQuery = new Parse.Query(contactObj);
console.log(req.body.From);
contactQuery.each(function(contact) {
and the body of the each call never gets called.
Is this allowed, and if so, what am I doing wrong here?
Update -- The entirety of the webhook code block is:
app.post('/receiveSMS', function(req, res) {
console.log('receive SMS');
console.log(req.body.Body);
res.send('Success');
if(req.body.Body.toLowerCase() == "in" || req.body.Body.toLowerCase() == "out") {
twilio.sendSMS({
From: "(xxx) xxx-xxxx",
To: req.body.From,
Body: "It's been noted, and notifications have been sent. Check us out!"
}, {
success: function(httpResponse) {
console.log(httpResponse);
response.success("SMS Sent!");
},
error: function(httpResponse) {
console.error(httpResponse);
response.error("Uh OH, something went wrong");
}
});
if(req.body.Body.toLowerCase() == "in") {
console.log("in was received");
// eventQuery
var contactObj = Parse.Object.extend("Contact");
var contactQuery = new Parse.Query(contactObj);
console.log(req.body.From);
// contactQuery.equalTo("phone", req.body.From);
contactQuery.first({
success: function(contact) {
console.log("found contact");
console.log(contact);
}, error: function(error) {
alert("Error: " + error.code + " " + error.message);
}
});
}
}
});
This code is called and the logs "console.log('receive SMS')" and the like are all called, except for what is inside the query's first call.
Queries on tables is fine, but you can't use the each() function, as that is restricted to only work in background jobs.
You'll have to use find() or first() or get() depending on your needs.
UPDATE
OK, after seeing your full code I have some ideas as to why it isn't working. First off you're sending res.send("Success"); before you're finished, I'm not positive but I think this causes it to stop running the rest of your code (haven't checked, could be wrong).
Also you're doing multiple async operations without chaining them so the contactQuery.first() will run before the twilio.sendSMS() is finished.
Inside twilio.sendSMS() you're calling response.success() / response.error(). These are for cloud methods, not web hooks, so I expect these would be throwing errors server-side (check the logs on the Dashboard).
Inside contactQuery.first() you are using alert() which isn't supported in cloud code.
I'm not sure if those mistakes will be caught early and throw errors or if they'll raise run-time exceptions, but they should be fixed, your code re-deployed and try again. Then report any errors in the server logs.
Yes, it's allowed, I'm using the same web hooks.
My guess is that you probably have defined security restriction on your Contact class that prevent the query to fetch anything. What's the security setting on this class ?
You can either try to relax the constrains, or login as a dummy user, and execute the query (approach that I chose).
cheers
-A

Wrong Error Code in Angular.js $resource responce

I have a function that lists the databases attached to a SQL server by making an API call.
function dbList(resource, args, scope, server){
// Recieves a list of DBs from the API and adds it to the scope
scope.loadingResponse = true;
resource('http://localhost:1000/apiv1/servers/:server/databases',
{server: server}).get(args).$promise.then(function (result) {
scope.databases = result.databases;
scope.loadingResponse = false;
}, function(error){
console.log(JSON.stringify(error));
errorHandler(scope, error)
})
}
It is called from my controller like:
dbList($resource, args, $scope, 'SERVER1');
It passes any errors it encounters to my error handler, which evaluates them:
function errorHandler(scope, error){
// Displays the error message and ends the loading animation
var err_code = error.status;
var err_message = 'Error Code ' + error.status + ': ';
console.log(JSON.stringify(error))
if (err_code == 401){
err_message += 'Unauthorized. Cookie expired or nonexistent.';
}
else if (err_code == 400) {
err_message += 'Missing parameter. Ensure all necessary fields are filled'
}
else if (err_code == 404) {
err_message += 'Resource not found. Ensure that it exists.'
}
else if (err_code == 405) {
err_message += 'Method not allowed. This could be caused by XHR Cross Domain Option requests.'
}
else if (err_code == 409) {
err_message += 'The Resource you wish to use is in use. Ensure that there is no name conflict with an attached database.'
}
scope.loadingResponse = false;
scope.error = err_message;
}
I'm making a call to the API without submitting the token I have to verify with, and am getting a 401 Error according to the Firefox console. This is the expected behavior when the API is access without the token. So I expected $scope.error to be set to Error Code 401: Unauthorized. Cookie expired or nonexistent.
However, what I am getting is Error Code 404: Resource not found. Ensure that it exists.
The Firefox console reads:
[13:39:20.419] GET http://localhost:1000/apiv1/servers? [HTTP/1.0 401 UNAUTHORIZED 5ms]
[13:39:20.413] "{"data":"","status":404,"config":{"transformRequest":[null],"transformResponse":[null],"method":"GET","url":"http://localhost:1000/apiv1/servers","params":{},"headers":{}}}"
How and why has angular.js transformed my 401 into a 404, and how can I access the correct status code?
ETA:
The problem turned out to be a cross-domain request issue caused by the Flask API I was using to run things from. See my answer below
The answer turns out to be a problem with the back end, which was done in Flask. A decorator was used to correctly set up Access-Control-Allow-Origin headers. Unfortunately, the decorator doesn't apply to errors that are done using the abort() function. The way around this is to use this decorator, and set things up like this:
if verify(req):
do stuff ...
else:
return jsonify({'error': 401}), 401
If the error is set up as a json return with an error code, the decorator will reach it.

Categories

Resources