I have the following service that runs when I navigate to a products page:
app.factory('ProductService',['$http','$location',function($http,$location){
var factory = {};
factory.getAll = function(){
$http.get('/products').success(function(response){
console.log('success callback hit');
if(response.status === 401){
console.log(response);
$location.path('login');
}
}).error(function(){
console.log('error');
});
};
return factory;
}]);
In my express router, I check if req.isAuthenticated() and if not (which is the case I'm testing), I call:
return res.status(401).send("Not Authorized");
That's the only place in my server where I send a 401 response, so I know the $http.get(/products) is going to the right place, and I see the get request returning 401 in my console, but why aren't any of my callbacks being hit? (Nothing is logged to the console and I don't get redirected on the client.) I read something about needing to reject the promise if I'm using global interceptors, but I don't think I am using any interceptors? EDIT: This is why I don't think it's a duplicate of the question suggested since I'm not using custom interceptors.
UPDATE: My error handler was getting called, just nothing was logged in my node.js command window (duh, because it's on the client). Thanks for the help everyone!
My error handler was getting called, just nothing was logged in my node.js command window (duh, because it's on the client). Thanks for the help everyone!
Related
I'm making a POST request to a TOMCAT server using AngularJS. Below is a snippet of that code.
$http(<myRequest>).then(function(response) {
$scope.info = response.data;
}, function(response) {
$scope.error = response.data
});
This works fine as long as the server is up and running. In case of any error on the response, it populates the $scope.error variable with the error message. However, if the server is down, when I click the link that makes this request nothing is shown on the page, I can only see the error on the console of the browser.
How do I show this error on the page? I want to somehow notify the user that the server is down.
Regarding the docs:
A response status code between 200 and 299 is considered a success status and will result in the success callback being called.
That said, if your error handler gets called you may check for the status property of the response object. Values in the 400 or 500 range indicate problems that will prevent the server from processing your request. If you are configuring the server yourself, you are able to make up your own error codes and interpret them client side.
$http(<myRequest>).then(function success (response) {
$scope.info = response.data;
}, function error (response) {
if (response.status === <server is down http status>) {
//do something here
$scope.error = "server is down msg";
}
else {
$scope.error = response.data;
}
});
I tried to post data to a non-existent server which gave me the status code -1. If your server is really down, you may have to check for this value.
Edit: There's also a statusText property within your response that could be helpful :)
I’m trying to implement authentication in my angularjs app.
I’ve read some articles about doing this properly. Here is one, for instance: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec
But I can’t realize how to make it respond on wrong username/password pair.
Let’s have a look at this code :
authService.login = function (credentials) {
return $http
.post('/login', credentials)
.then(function (res) {
// populate user info
}
);
};
I’ve tried to add here a second callback to “then” method and use “success”/”error” methods instead of “then” and I’ve tried to response on $http.post request with different error like 400 and 500 via status, but in any case all the errors are handled by the success method and callback.
What am I doing wrong? How to catch wrong password/username response in angular?
It was actually my own fault. My custom Intereptor simply swallowed authenticaion errors.
This question already has answers here:
Suppress Chrome 'Failed to load resource' messages in console
(3 answers)
Closed 5 years ago.
I'm trying to figure out how to suppress http request and response errors in my app, for example when a bad request is made to my server, I don't want the error to be logged into the browser console. I've tried overriding the $exceptionHandler, but that logic works for all exceptions except HTTP errors, those are still logged to the browser. I've also created HTTP interceptors but the global 400 Bad Request error appears before the logic that I've put in my responseError:
'responseError': function (rejection) {
console.log(rejection);
return $q.reject();
}
That doesn't suppress the error either, any ideas?
EDIT
The error I'm getting is this:
POST http://localhost:38349/token 400 (Bad Request)
Actually Angular doesn't log this.
It's the XMLHttpRequest object that doing that (same issue here with JQuery). I extracted the logic from Angular and made a working standalone example:
var method = 'POST';
var url404 = '/tnseiartneiasrt/arsntiearsntiasrntiarnstsie';
var xhr = new window.XMLHttpRequest();
xhr.open(method, url404, true);
xhr.onreadystatechange = function() {
if (xhr && xhr.readyState == 4) {
console.log('should have logged an error already :(');
}
};
xhr.send(null);
As you can see, it's the xhr object that logs it. There might be a way to disable all console.log before triggering the xhr request but I think it's better to either
Redesign your error flow to return a status code of 200 embeded with an internal error code in the body
Live with the console logging (the average user doesn't even know about the console anyways)
I chose the second option because I think it's easier to understand as it doesn't require extra logic when someone reads your code.
Hope this helps :)
I'm having some trouble with error handling in a little angularjs application. I'm interacting with a Flask backend and a Postgres DB.
I have a factory service
appointServices.factory('Appointments', ['$resource', function($resource){
return $resource(someUrl, {}, {
query: { ... }
,
create: {
method: 'POST'
,url: 'http://somedomain:port/new/:name/:start/:end/:treatment'
,params: { start: '#start', end: '#end', name: '#name', treatment: '#treatment' }
,isArray:false
}
});
}
]);
Inside a controller I'm making the following call
Appointments.create($scope.appointment, function(value, responseHeaders) {
// success handler
console.debug('success: ', JSON.stringify(value));
}, function(httpResponse) {
// error handler
console.debug('error: ', JSON.stringify(httpResponse));
});
Here $scope.appointment contains the relevant parameters for the create action.
Now, in the backend I'm able to catch DB errors involving constraints and I'm trying to return an error code with a 'meaningful' message. So I have a python method
def create(name, start, end, treatment):
try:
...
transaction_status = 'ok'
code = 200
except IntegrityError as e:
...
transaction_status = 'IntegrityError'
code = 500
finally:
...
return make_response(transaction_status, code)
Everything works fine, I'm able to talk to the backend, create new data and insert this in the DB. As I said, any violation of the constraints is detected and the backend responds
curl -X POST "http://somedomain:port/new/foo/bar/baz/qux" -v
...
< HTTP/1.0 500 INTERNAL SERVER ERROR
...
IntegrityError
So, the problem is, no matter whether the action create was successful or not, the intended error handler specified inside the controller is always fired. Moreover, I always end up with a status code 404 in the httpResponse. Firebug shows correctly the code 500 as above, though.
Anybody has any idea of why I'm getting this behavior?
Any suggestions on how to improve the error handling mechanism are also welcome.
Thx in advance.
P.S. Following the documentation on $resource I have also tried variations on the factory service call, e.g.
Appointments.create({}, $scope.appointment, successCallback, errorCallback);
Appointments.create($scope.appointment, {}, successCallback, errorCallback);
with the same results.
Update:
Forgot to mention the important fact that I'm interacting with the backend via CORS requests. The POST request in create above is having place with the OPTIONS method instead. As I mentioned everything is working correctly except for the error response.
Under further investigation, I tried to isolate the factory service, in case I did something wrong, and I also tried the approach shown in the credit card example ($resource docs), but with no positive result.
However, I came up with two workarounds. Firstly, I was able to create a plain JQuery POST request, as in the example shown in the docs. This time, the request is not replaced by OPTIONS and I got the error code correctly.
I also managed to connect to the backend with the low-level $http service as follows:
var urlBase = 'http://somedomain:port/new/:name/:start/:end/:treatment';
var url = urlBase.replace(/:name/g, $scope.appointment.name);
url = url.replace(/:start/g, $scope.appointment.start);
url = url.replace(/:end/g, $scope.appointment.end);
url = url.replace(/:treatment/g, $scope.appointment.treatment);
// force method to be POST
var futureResponse = $http({ method: 'POST', url: url });
futureResponse.success(function (data, status, headers, config) {
console.debug('success: ', JSON.stringify(data));
});
futureResponse.error(function (data, status, headers, config) {
console.group('Error');
console.debug(JSON.stringify(status));
console.debug(JSON.stringify(data));
console.groupEnd();
});
This time, as in the case of JQuery, the request is done effectively with POST and error codes are correctly received.
Notice also that I'm not calling $http.post but I set the method to POST as part of the object parameter to $http, otherwise the connection takes places with OPTIONS as before.
Still trying to figure out what is happening with $resource.
in AngularJs 1.2.x, the docs only provide a rejection object, how can we see the actual response object? (to see things like http status code)
edit: here's an example from the docs:
// register the interceptor via an anonymous factory
$httpProvider.interceptors.push(function($q, dependency1, dependency2) {
return {
'responseError': function(rejection) {
// do something on error
if (canRecover(rejection)) {
return responseOrNewPromise
}
return $q.reject(rejection);
};
});
that example shows some unknown rejection object (no docs on what it's members are). the old (deprecated responseInterceptors allow query of the response object. (check for status=401, for example) how are you supposed to query for 401 service errors with the new interceptor functionality?
i am coding my usage of this to the point of being able to run it,
and so i set a breakpoint, and see that the "rejection" object has a .status property.
if a server doesn't exist, it will == 0
otherwise, it seems to return the http status code. (i see 404 so far)
I havent coded a real service point so i'll update this answer and/or accept it once i get that done.
update: yes, the .status field returns the http response status, and 0 if server not found. so this is the valid answer!