I'm using Express with NodeJS and AngularJS in front-end. After click here, add data there, update some record here, show a list there, I get net::ERR_CONNECTION_RESET. It's strange, after 8 or 9 navigations through the application, I got this error. Before this, the AJAX calls are doing fine.
An example of an AngularJS controller:
app.controller('GrupoController', ['$scope', '$location', '$routeParams', 'GrupoService',
function ($scope, $location, $routeParams, GrupoService) {
$scope.carregarDependenciasMeusGrupos = function () {
GrupoService.carregarDependenciasMeusGrupos().then(function (result) {
$scope.data = {
grupos: result.Data
};
});
};
$scope.editarGrupo = function(grupo) {
$location.path('/editar-grupo/' + grupo.Id);
};
}]);
And also an example of a HTTP call:
function ajax(url, async, method, params, isJson, showLoading) {
var deferred = $q.defer();
$http.post('http://localhost:3000' + url, params).success(function(result) {
if (result.StatusCode === 403) {
$location.path('/login');
} else {
if (result.Success) {
deferred.resolve(result);
} else {
deferred.reject();
if (result.ErrorMessage) {
alert(result.ErrorMessage);
}
if (result.RedirectTo) {
window.location.href = result.RedirectTo;
}
}
}
}).error(function(err) {
deferred.reject();
});
return deferred.promise;
}
This is the approach I'm using with Express and NodeJS to create an action that is called through that AJAX method above:
app.post('/grupos/get-dependencies-to-grupos', app.ensureAuthentication, function(request, response, next) {
query.openConnection().then(function(connection) {
var gruposRepository = new repositories.Grupos(connection);
gruposRepository.getDependenciasToGrupos(
request.headers["authorization"], request.body.grupoId)
.then(function(result) {
response.json({ StatusCode: 200, Data: result });
}, function(getDependenciesError) {
response.json({ StatusCode: 500, ErrorMessage: getDependenciesError });
});
});
});
After 8 or 9 navigations, the app stopped to work suddenly. Can you guys help me? Thank you!
What happens if "getDependenciasToGrupos" promise result is an error, you don't have "catch".
So if it is in error, there is no http response from the server (nodejs), and the browser, after waiting for responses for few requests, shuts down the connexion.
Try to add a catch handler to the promise :
gruposRepository.getDependenciasToGrupos(
request.headers["authorization"], request.body.grupoId)
.then(function(result) {
response.json({ StatusCode: 200, Data: result })
.catch(function(error){response.json({ StatusCode: 503, Data: error})});
Related
I'm using Angular 1.6.4, Express 4.15.2 and express-session.
I am trying to catch if the user is unauthorized to access a certain route by checking the existence of req.session.user parameter. If he's not, I'd like to send a 401 response status and change the state in Angular.
The problem is that I am not getting any response object to check the status of.
I have tried using an interceptor, logging out error.response.body, logging out everything really to find out where it is that I'm losing the response object.
Here's some code, any help would be greatly appreciated!
express:
app.get('/update', sessionCheck, function(req, res) {
res.send('session');
});
function sessionCheck(req, res, next){
if(req.session.user) {
next();
} else {
console.log('before');
return res.status(401).send('Unauthorized');
console.log('after');
}
}
angular:
.state('update', {
url: '/update',
views: {
"": {
templateUrl: 'templates/update.html',
controller: function($http) {
return $http.get('/update').then(function(response) {
console.log('Ok response' + response);
}, function(error) {
console.log('Error response' + error.response.body);
});
},
},
"carousel": {
templateUrl: "templates/carousel.html"
},
"footer": {
templateUrl: "templates/footer.html"
}
}
})
network screen
Have you tried to do this using an interceptor?
You can try in this way:
anyModule.service('yourInterceptor', function($q) {
var service = this;
service.responseError = function(response) {
if (response.status == 401){
//do something
}
return $q.reject(response);
};
})
Note that here we are dealing with responseError.
You need to register you interceptor too in a config function:
$httpProvider.interceptors.push('yourInterceptor');
You can see this for more information about this interceptor:
Capture HTTP 401 with Angular.js interceptor
UPDATE:
You can register an interceptor in this way too:
app.factory("YourInterceptor", ["$q", "$rootScope", "$location",
function($q, $rootScope, $location) {
var success = function(response) {
//do something
return response;
},
error = function(response) {
if(response.status === 401) {
// do something
}
return $q.reject(response); //reject on error
};
return function(httpPromise) {
return httpPromise.then(success, error);
};
}
Then you register your interceptor in this way (in a config of the module):
$httpProvider.responseInterceptors.push("YourInterceptor");
Note that you push the interceptor in responseInterceptors. This work to me.
I am trying to develop a user management feature for a website using the MEAN.io stack. What I'm trying to do has worked in the past for other models on the same site so I'm not sure what is going on. My issue is that I am trying to get all the User models from the MongoDB database and pass them to an AngularJS controller so that I can display their information on a user management page. To that end, I added this function to the User controller in the backend:
exports.readUsers = function(req, res) {
var decodedToken = req.decodeToken;
var User = mongoose.model('User');
var id = req.params.id;
existUser(decodedToken, function(err, user) {
if(err) {
return sendError(res, 'INVALID_TOKEN');
}
User.find({})
.select('username')
.exec(function(err, results) {
if(err) {
return sendError(res, err);
}
res.json({success: true, userList: results});
});
});
}
This line to the routing code:
router.get('/users/all', Authorization.token, user.readUsers);
And this AngularJS controller for use with the frontend:
(function () {
"use strict";
var app = angular.module("GAP");
app.factory("UserEditFactory", function UserEditFactory($http, API_URL, AuthTokenFactory, $q) {
"use strict";
return {
readUsers: readUsers
};
//Get all users in the DB
function readUsers() {
if(AuthTokenFactory.getToken()) {
return $http.get(API_URL + "/users/all");
}else {
return $q.reject({
data: "valid token required"
});
}
}
});
app.controller("userPageController", ["UserEditFactory", "$scope", "$http", "$window", "API_URL",
function(UserEditFactory, $scope, $http, $window, API_URL) {
UserEditFactory.readUsers().then(function(data) {
console.log(data.data);
$scope.users = data.data.userList;
}, function(response) {
console.log(response);
});
}
]);
})();
When I load the page that is supposed to display this information, no data is displayed. I have determined that the AngularJS controller is calling the second function which I understand is the one used to respond to an error.
Further investigation of the object returned by the $http.get call reveals no data, and a status of -1. I'm not sure why this is happening, because I have used this exact pattern of code to get and display data from other models in the database on the same site. I can manually make HTTP calls to those working functions from this controller, and everything works fine. I'm not sure where to go from here or how to learn more about the issue. Can anyone offer insight? Let me know if you need more information.
Edit: As requested, here is the code for the AuthTokenFactory, which is an app.factory object in a common JS file.
app.factory('AuthTokenFactory', function AuthTokenFactory($window) {
'use strict';
var store = $window.localStorage;
var tokenKey = 'auth-token';
var userKey = "username";
return {
getToken: getToken,
setToken: setToken,
setUsername: setUsername
};
function getToken() {
return store.getItem(tokenKey);
}
function setToken(token) {
if (token) {
store.setItem(tokenKey, token);
} else {
store.removeItem(tokenKey);
}
}
function setUsername(username) {
if (username) {
store.setItem(userKey, username);
} else {
store.removeItem(userKey);
}
}
});
I copied the following code from the web to work with JWT authorisation, but it does not work. In particular the $location.path command has no impact - the redirect does not take place. I also tried with $state.go, but that led to bigger errors. I don't fully understand what $q is referring to here, not what is waiting for the promise to unwind, but the issue is $location.path not taking the user back to the login screen (nor are the proposals below with respect to $state changes).
$httpProvider.interceptors.push(function($q, $location, $localStorage) {
return {
'request': function (config) {
config.headers = config.headers || {};
if ($localStorage.token) {
config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
},
'responseError': function(response) {
if(response.status === 401 || response.status === 403) {
console.log("app.js: httpInterceptor caught authorisation status response");
delete $localStorage.token;
$location.path('/'); // to login page
// $state.go('login');
}
return $q.reject(response);
}
};
});
}
To test, I send a message that creates an server error, catch that in devtools on the way back, and then manually set response.status = 403. The redirect is clearly parsed but does not lead to the redirect. I can see that the login screen is put back on the screen, but is then immediately overwritten by a different view.
This is the factory $http ajax request. Is it possible that the deferred $q I use here is interfering with that in the interceptor?
$http(httpObj)
.success(function (response) { // returns 0: mongo resto data, 1: wpserver report
console.log("%s succesful, response: %s", method, response);
if (!updateNotAdd) {
Restos.data.restos.push(response[0]); // add to local copy of data
} else {
// replace existing entry with new information
var idxToReplace = _.findIndex(Restos.data.restos, function(r) {
return r.qname === resto.qname;
});
// copy over all data from editor model to database
_.assign(Restos.data.restos[idxToReplace], resto);
}
var response = {
success: true,
id: response[0]._id,
message: response[1]
};
$rootScope.$broadcast("ajaxresponse", response);
deferred.resolve(response);
})
.error(function (msg) {
// console.log(msg);
var response = {
success: false,
message: msg
};
$rootScope.$broadcast("ajaxresponse", response);
deferred.resolve(response);
});
return deferred.promise;
You shouldn't have an issue leveraging ui-router here. You need to use the $injector service to get a reference on the $state service. Observe the following change...
$httpProvider.interceptors.push(function($q, $location, $localStorage, $injector) {
return {
'request': function (config) {
config.headers = config.headers || {};
if ($localStorage.token) {
config.headers.Authorization = 'Bearer ' + $localStorage.token;
}
return config;
},
'responseError': function(response) {
if(response.status === 401 || response.status === 403) {
console.log("app.js: httpInterceptor caught authorisation status response");
delete $localStorage.token;
$injector.get('$state').go('login');
}
return $q.reject(response);
}
};
});
}
The bigger issues you're experiencing are caused by a circular dependency due to ui-router injecting $http into $TemplateFactory - leading to a circular reference to $http inside $httpProvider when you attempt to inject $state (which doesn't yet appear to be in your interceptors injection signature anyways)
Not sure whether you want to use, but probably this would redirect:
$window.location.href = url;
I am new to AngularJS.
I am getting an error while trying to call PUT restful webservices from AngularJS. This is my factory method.
.factory('EmployeeService',function($q,$http){
Approval:function(userId,firstName){
var deferred = $q.defer();
$http({
method: 'PUT',
url: '/AngularExample/user',
params:{
lastName:userId,
firstName:firstName
}
}).
success(function (data) {
if (data != null || data != 'undefined') {
deferred.resolve( data);
}
})
.error(function (error) {
console.log('error');
});
return deferred.promise;
})
EmployeeService is my service name
$scope.showAlert = function () {
EmployeeService.Approval( $stateParams.userId,$stateParams.firstName).then(function (approval) {
$scope.approve= approval;
})
This is the error getting while calling PUT REST Api call in Java.
Angular JS version using :1.3.15 .
Rest api call is not triggering from angular to Rest Back end and not getting any error in back End.
Error getting in the angular js :
unexpected Request PUT No more request expected
at $httpBackend (angular-mocks.js:1180)
at m (angular.js:9628)
at $get.f (angular.js:9344)
at angular.js:13189
at l.$get.l.$eval (angular.js:14401)
at l.$get.l.$digest (angular.js:14217)
at l.$get.l.$apply (angular.js:14506)
at HTMLButtonElement.<anonymous> (ionic-angular.js:9958)
at HTMLButtonElement.c (angular.js:3014)
at triggerMouseEvent (ionic.js:2804)
It works in Postman.
i am using service and simple call the our REST API
//in app/js
var serverUrl = 'http://xxxxx.in/api';
.service('UserBankDetails', ['$http',
function($http) {
this.userBankDetailsAdd = function(data, cb) {
var res = $http.put(serverUrl + "/user_bank_account", data);
res.success(function(data, status, headers, config) {
cb(data);
});
}
}
])
//simple call from controller
UserBankDetails.userBankDetailsAdd($scope.userBankInfo, function(res) {
console.log(res);
if (res.data === 1) {
$scope.account_found = true;
} else {
$scope.account_found = false;
}
});
I'm setting up authorization with AngularJS and angular ui router.
If a user tries to access a route which requires authorization, the server returns a 401 status code.
I have created an HTTP response interceptor which checks for the 401 status code.
If the code is 401, it is supposed to redirect to the log in page, but this does not work.
It catches the 401, but does not redirect. Here is the code for the interceptor:
app.config(['$httpProvider', function ($httpProvider) {
// This is just for to check for XHR requests on the server
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
$httpProvider.responseInterceptors.push(['$q', '$location', function ($q, $location) {
return function (promise) {
return promise.then(
// Success: just return the response
function (response) {
return response;
},
// Error: check the error status to get only the 401
function (response) {
if (response.status === 401)
$location.url('/users/login');
return $q.reject(response);
}
);
}
}]);
}]);
EDIT: It seems to be working if I do it like this:
$timeout(function() { $location.url('/users/login'); }, 0);
I guess that puts it last in the execution stack and changes the execution context. Does anyone know more about this, or if this indeed does work or only seems so?
I add the same issue. So I changed my code to use the $location.path (not url)
$location.path("/users/login");
Can you try that
angular.module('yourApp').config(function ($httpProvider) {
var logsOutUserOn401 = ['$q', '$location', function ($q, $location) {
var success = function (response) {
return response;
};
var error = function (response) {
if (response.status === 401) {
//redirect them back to login page
$location.path('/login');
return $q.reject(response);
}
else {
return $q.reject(response);
}
};
return function (promise) {
return promise.then(success, error);
};
}];
$httpProvider.responseInterceptors.push(logsOutUserOn401);
});
(source : http://arthur.gonigberg.com/2013/06/29/angularjs-role-based-auth/)
I have it working with
$window.location.href='...'
I finally solved it, but I still don't know why it didn't work. Anyway, I had to use this to redirect: (state transition)
$injector.get('$state').transitionTo('users.login');
this is how we added a response interceptor in our project. its working for us.
$httpProvider.interceptors.push(function($q, $rootScope, $location,
$cookieStore) {
return {
'responseError' : function(
rejection) {
var status = rejection.status;
var config = rejection.config;
var method = config.method;
var url = config.url;
if (status == 401) {
$rootScope.shouldRedirect = true;
$rootScope.urlAttempted = url;
$location
.path("/login");
} else if (status == 403) {
$location
.path("/accessForbidden");
} else {
}
return $q.reject(rejection);
}
};
});