Wrong Error Code in Angular.js $resource responce - javascript

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.

Related

JS fetch() | How to hide console error on 404? [duplicate]

Is there a way with the HttpClient to remove error messages from the browser console?
My current code looks like this:
getStuff(stuffId: string): Observable<Stuff[]> {
return this.httpClient.get<Stuff[]>(this.stuff() + stuffId + '/stuff/').pipe(
catchError((err) => {
console.log(err.status);
if (err.status === 404) {
console.log('Not found');
}
})
);
}
My console.log('Not found') within the if statement is executed, but it still throws the standard error to the console.
My goal: nothing red in the console :)
UPDATE:
The errors are not thrown in Firefox, but in Google Chrome. Why..?
The standard error you are seeing in console is actually not from code. Its from network, due to API error. The browsers consider and understand standard http response codes. So, whenever any response code other than 2xx is returned by any http request, they consider it an error and show it in red in console.
Unfortunately you cannot remove it. That's done by browser.
Callback to catchError has to return an Observable so you can just return for example EMPTY that just completes and emits nothing:
import { EMPTY } from 'rxjs';
...
catchError((err) => {
console.log(err.status);
if (err.status === 404) {
console.log('Not found');
}
return EMPTY;
});

WebAPI and 401 vs 200

I am building a WebAPI as a learning project and attempting to use best practices. My first attempt is a authentication API, which takes an authentication object (JSON):
{
username: myusername,
password: mypassword
}
it calls my API on /api/authenticate as a POST, passing the object.
In my .Net code, I do some checks, and if the username/password pass, I create a jwt token, and return it with roles. My API returns a 200 with the token in the body (response in Chrome developer tools shows "ey.....", which is my jwt).
If I get an invalid username/password, I return a 401.
I'm not sure this is right. Should I rather return a 200 - and some other payload in the body? (Not sure what), and then should my successful login return JSON, such as:
{
success: true,
error: null
token: "ey.....",
}
A failed login return:
{
success: false,
error: null
token: null,
}
and then an error:
{
success: false,
error: 500
token: null,
}
And then client side code uses that to decide what to do? I'm trying to work on a best practice here to learn how to handle this in WebAPI.
I don't think there is really a "best practice" here. Some APIs return an error object like you did with JSON. That's completely fine. Other APIs return HTTP errors (401, 500, etc...). Other APIs return both. There are pros and cons to each method, so choose whatever you like or suits your needs best.
If you go with the first method, don't limit yourself to returning HTTP codes. Instead, return codes that give you and the consumers of your API more specific references to the errors. For example, code 401 doesn't tell me why the authentication failed. Probably that's fine for security, but I'm only using it here as an example, so instead you can return code 1001 for incorrect credentials, 1002 for an account that is locked, 1003 for an account that is pending approval, etc...
Pros of the first method: the API consumer can handle everything in the same code using a simple if...else or switch logic. It is also easier to test. The cons: you still need to use try...catch, because the request to the API may still fail, so the consumer code will have the above logic plus the try...catch logic.
Pros of the second method: it is more inline with the way we usually do things. Use try...catch to handle all errors, and the code inside will only be for the successful path. The cons: a little harder to test and you're stuck with the HTTP error codes.
The third method is a combination of the two. In some cases it is probably an overkill and adds some unnecessary complexity and repetition, but in other cases it can combine the benefits of the two worlds.
Here I give a different way of returning response message...
I hope, This will help you in returning the response message...
// For login success
In the below code, it shows the success response...
return Content(HttpStatusCode.Ok, error); This will helps to return the status code in the header of the Postman Tool.
if (result == null)
{
var error = new
{
Success = "true",
Token = "your token"
};
return Content(HttpStatusCode.Ok, error);
}
//for Unauthorized user login
In the below code, it shows the Unsuccess login response...
Here we can mention the error status to the user in response...
return Content(HttpStatusCode.Unauthorised, error); This will helps to return the status code in the header of the Postman Tool.
if (result == some condition)
{
var error = new
{
Error = new
{
StatusCode = HttpStatusCode.Unauthorised,
Message = "Invalid Credential...! ",
InternalMessage = "Some message"
}
};
return Content(HttpStatusCode.Unauthorised, error);
}
// for error
In the below code, it shows the Unsuccess login response...
Here we can mention the error status to the user in response...
return Content(HttpStatusCode.InternalServerError, error); This will helps to return the status code in the header of the Postman Tool.
if (result == somecondition)
{
var error = new
{
Error = new
{
StatusCode = HttpStatusCode.InternalServerError,
Message = "Error in functionality...!",
InternalMessage = "Some message"
}
};
return Content(HttpStatusCode.InternalServerError, error);
}

Error conditions for NPM Request lib

An error is being passed by the callback in my request function. I am trying to determine under what conditions an error is passed to the callback.
var request = require('request');
request('http://www.google.com', function (error, response, body) {
if(error){
//why or when would an error be created?
}
else if (response.statusCode == 200) {
console.log(body) // Show the HTML for the Google homepage.
}
else{
// when would this happen ?
}
})
the documentation doesn't seem to cover what conditions will cause an error object to be created and passed. Right now I just assume anything but a 200 or 300 will cause an error to be created, but I am just guessing.
request library uses the node.js http module internally for making GET request. From it's doc:
If any error is encountered during the request (be that with DNS
resolution, TCP level errors, or actual HTTP parse errors) an 'error'
event is emitted on the returned request object.
I guess you have to go though the http module source to exactly find out what are the errors.

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

Detect fail of chrome.extension.sendRequest

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

Categories

Resources