Inject http into httpProvider in AngularJS - angularjs

I want to make it so that users are automatically logged out by having the client terminate the session (as opposed to letting the session die on its own). I pushed an interceptor onto the $httpProvider which allows me to set and reset the timeout timer, but the problem is that I can't figure out how to call the logout function which requires $http. This always produces a circular dependency. Is there any way to do this?
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(
function() {
return {
response: function(response) { $http({ ... }); }
})}
If I make $http a dependency, I get a circular dependency, but without the $http dependency, the call to $http obviously doesn't work.

You should be careful using $http inside an interceptor as it has the potential to cause an infinite loop. Consider refactoring so $http isn't required
That said you can try injecting the $injector instead. Then where you want to make the $http request just use $injector.get('$http')
app.config(['$httpProvider, $injector', function($httpProvider, $injector) {
$httpProvider.interceptors.push(
function() {
return {
response: function(response) { $injector.get('$http') }
})}

You need to inject $http dependancy inside theinceptor.push function, you could also inject other dependencies from there.
Code
app.config(['$httpProvider',
function($httpProvider) {
$httpProvider.interceptors.push(
function($http) { //<--here you could make dependency available.
return {
response: function(response) {
$http({...});
}
})
}])

I used a crossover of the previous answers (use $injector, but in the push() ) to get it working as expected:
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function($q, $injector) {
...
//now get $http like this and use it as needed:
$injector.get('$http')

Related

In angular 1.x are interceptors always factories?

I'm trying to wrap my head around interceptors, I still can't figure them out. Can someone explain a tad more for me about if they are a service, a config, etc?
Interceptors can be either a named factory or an anonymous factory.
app.config(function ($httpProvider) {
//register the interceptor factory
$httpProvider.interceptors.push('myHttpInterceptor');
// alternatively, register the interceptor via an anonymous factory
$httpProvider.interceptors.push(function($q, dependency1, dependency2) {
return {
'request': function(config) {
// request transform
},
'response': function(response) {
// response transform
}
};
});
});
Interceptors are registered during the config phase of the AngularJS app. Their factory functions (either named or anonymous) are invoked during the $get phase of the $http service.
For more information, see AngularJS $http Service API Reference - Interceptors

Maintain session using Interceptor cookies/ server-sessions

Firstly, apology if this question does not make sense. I am developing code for session management for my mean stack app. From last few days, i found lots of way to implement it which are using either cookies, sessions or http - headers. I tried to implement, but did not get success.
I successfully link the interceptor with my code. Code is listening to each req/res.
Here is some code:
app.js
angular.module('MyApp', [
'ngMaterial',
'ngMdIcons',
'ui.router',
'e3-core-ui.services',
'e3-core-ui.utils'
])
.config(['$stateProvider', '$routeProvider','$httpProvider','$mdThemingProvider', '$mdIconProvider', function($stateProvider, $routeProvider, $httpProvider, $mdThemingProvider, $mdIconProvider) {
$httpProvider.interceptors.push('YourHttpInterceptor');
...
Interceptor-code
angular.module('MyApp')
.factory('YourHttpInterceptor', ['$q',
function($q, ) {
return {
'request': function(config) {
console.log("req");
return config;
},
// Optional method
'response': function(response) {
// do something on response success
console.log("inside the response ");
return response;
},
// optional method
'responseError': function(rejection) {
// Here you can do something in response error, like handle errors, present error messages etc.
console.log("inside the response error ");
return $q.reject(rejection);
}
};
}]);
I will be very thankful for your time and help.
In Meanjs you have the authentication controller
mean/modules/users/client/controllers/authentication.client.controller.js
but if you want to use the authentication service in your interceptor, just be aware that injecting a dependency isn't that easy as doing it in a controller.
you'll need to use $injector
var AuthService = $injector.get('Auth');
then you'll have to be sure your user is authenticated and check that in your request function, something like
if (!Authentication.user) {
$location.path('/'); // or a login page
}

AngularJS $resource interceptors

How do I add interceptors to a $resource call?
Let's say I have a resource factory called Users, like so;
app.factory('Users', ['$resource', 'resourceInterceptor',
function ($resource, resourceInterceptor) {
return $resource(
'users/:user_id',
{
user_id: '#id'
},
{
query: {
method: 'GET', // Not changing the default method, just adding an interceptor
interceptor: resourceInterceptor // Is there any better way to do this.. like globally?
},
save: {
method: 'POST', // Same here
interceptor: resourceInterceptor // Again...
},
..., // And so on
}
);
}]);
and my resourceInterceptor service looks like;
app.factory('resourceInterceptor', ['$rootScope',
function ($rootScope) {
return {
request: function () {
// This function isn't executed at all?
$rootScope.loading = true;
},
response: function () {
$rootScope.loading = false;
},
responseError: function () {
$rootScope.loading = false;
}
};
}]);
First of all, the request intercept function is never executed, why not?
Secondly, having to hardcode the interceptor to existing $resource methods is very tedious , is there a way to easier assign interceptors to specific $resource calls, or maybe even assign an interceptor to all $resource calls?
To use an interceptor in a resource you should:
1 - Make an httpInterceptor with you request, response, responseError:
app.factory('myInterceptor', function () {
//Code
//return { request:...,
});
2 - Config this Interceptor in your app:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('myInterceptor');
}]);
Right now as you have config your httpProvider to has an interceptor wherever you inject $http you will use this provider so... you will excute your request, response and responseError funciton.
3 - Using it in a resource.
As $resource use $http and you have config a httpProvider globaly you will call your interceptors' func when you use your resource.
Second question:
You can not set an interceptor to a concrete $http object, they (interceptors) are set globally.
(Even if you set the interceptor before your module definition and then you remove it, you can not know the execution order)
What you can do if you do not want to override the interceptor property in each $resource action (as you write in your question) you can improve your interceptor.
app.factory('userLoadingInterceptor', function () {
//Code
return {
request: function(){
//Check if your are working with a url related with users
// and if so do things...
}
});
From the docs:
The interceptor object has two optional methods - response and responseError
I don't know what you want to achieve but generic HTTP interceptors might be an alternative.
A generic HTTP Interceptor should do what you want. You can find a sample here: Handle HTTP 302 response from proxy in angularjs.

Delay an angular.js $http service

I have some angular factories for making ajax calls towards legacy ASP.NET .asmx web services like so:
module.factory('productService', ["$http",
function ($http) {
return {
getSpecialProducts: function (data) {
return $http.post('/ajax/Products.asmx/GetSpecialProducs', data);
}
}
} ]);
I'm testing on a local network so response times are "too" good. Is there a smart way of delaying the $http a couple of seconds from making the call to simulate a bad connection?
Or do I need to wrap all calls to the factory methods in a $timeout ?
$timeout(function() {
productService.getSpecialProducs(data).success(success).error(error);
}, $scope.MOCK_ajaxDelay);
Interesting question!
As you mentioned yourself, $timeout is the most logical choice for a delayed call. Instead of having $timeout calls everywhere, you could push a response interceptor that wraps the $http promise in a $timeout promise, as conceptually outlined in the documentation of $http, and register it in one of your configuration blocks. This means all $http calls are affected by the $timeout delay. Something along the lines of:
$httpProvider.interceptors.push(function($timeout) {
return {
"response": function (response) {
return $timeout(function() {
return response;
}, 2500);
}
};
});
As a bonus to your "to simulate a bad connection?", you could reject or do absolutely nothing randomly, too. Heh heh heh.
The new chrome device emulator has a network throttling function:
To get there: In Google Chrome, press F12 to open the Developer Tools. Then, on the top left corner, click the "Toggle device mode" icon (left to the "Elements" menu).
Developing more on the answer of #stevuu
responseInterceptors seems to be depreceted (as of 1.2.20) I have modified the code to work on the interceptors mechanism:
$httpProvider.interceptors.push(function($q, $timeout) {
return {
'response': function(response) {
var defer = $q.defer();
$timeout(function() {
defer.resolve(response);
}, 2300);
return defer.promise;
}
};
});
You could use the $q service for defer().promise pattern:
function someFunction(MOCK_ajaxDelay) {
var deferred = $q.defer();
$http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(function(response) {
$timeout(function() {deferred.resolve({ success: true, response: response })}, MOCK_ajaxDelay);
}).error(function() {
$timeout(function() {deferred.resolve({ success: true, response: response } }, MOCK_ajaxDelay);
});
return deferred.promise;
}
someService.someFunction(500).then(function(data) {
if (data.success) {
$scope.items = data.response.d;
}
});
But if you are really mock testing, the better solution is to look into ngMock: http://docs.angularjs.org/api/ngMock.$httpBackend
While #stevuu's answer is correct, the syntax has changed in the newer AngularJS versions since then. The updated syntax is:
$httpProvider.interceptors.push(["$q", "$timeout", function ($q, $timeout) {
function slower(response) {
var deferred = $q.defer();
$timeout(function() {
deferred.resolve(response);
}, 2000);
return deferred.promise;
}
return {
'response': slower
};
}]);
You can achieve this using the promise api combined with a $timeout. The $http.post function returns a promise from which you can call .success and .error (these are http specific methods). This promise is resolved when the http request is complete. If you build your own promise then you can tell it to delay 2 seconds and then resolve when the http request is complete:
module.factory('productService', function ($http, $q, $timeout) {
return {
getSpecialProducts: function (data) {
var defer = $q.defer();
$http.post('/ajax/Products.asmx/GetSpecialProducs', data).success(
function(data) {
// successful http request, resolve after two seconds
$timeout(function() {
defer.resolve(data);
}, 2000)
}).error(function() {
defer.reject("Http Error");
})
return defer.promise;
}
}
});
But note - you will have to use promise.then(successCallback, errorCallback) functionality - that is, you'll lose the ability to access http headers, status & config from your controllers/directives unless you explicitly supply them to the object passed to defer.resolve({})
Links:
Defer/Promise Api
Http/Promise Api
Resolve egghead video
In response to the testing aspect of your question, Fiddler has a really useful function that helps when you need to simulate delays:
Click on the AutoResponders tab in Fiddler.
Add a rule with a regex that matches the URL of the request you want to delay.
Set the "respond with" to "*delay:1000" where the number is the delay in milliseconds.
The AutoResponder functionality in Fiddler is extremely useful for testing JS that involves a lot of http requests. You can set it to respond with particular http error codes, block responses, etc.
If you are using a service that returns a promise, then inside you should put a return before the $timeout as well because that returns just another promise.
return dataService.loadSavedItem({
save_id: item.save_id,
context: item.context
}).then(function (data) {
// timeout returns a promise
return $timeout(function () {
return data;
},2000);
});
Hope it helps someone!

Angular.js code with $httpProvider and promise. What does it do?

Could you explain in general what does this code do:
App.config(['$httpProvider', function ($httpProvider) {
$httpProvider.responseInterceptors.push('HttpSpinnerInterceptor');
$httpProvider.defaults.transformRequest.push(function (data, headersGetter) {
angular.element('.brand img').attr("src","<%= asset_path('brand/brand.gif') %>");
return data;
});
}]);
App.factory('HttpSpinnerInterceptor', function ($q, $window) {
return function (promise) {
return promise.then(function (response) {
angular.element('.brand img').attr("src","<%= asset_path('brand/brand.png') %>");
return response;
}, function (response) {
angular.element('.brand img').attr("src","<%= asset_path('brand/brand.png') %>");
return $q.reject(response);
});
};
});
I have completely no understanding except some guesses that it intercepts some response and injects a src attribute of image.
I do not understand how and when is HttpSpinnerInterceptor called and what the "promise" parameter is.
HttpSpinnerInterceptor is been called after each request issued by using $http service is completed (successfully or not), but before promise is been resolved to caller (so you can defer result). Actually transform request is not needed, because it does mostly same as HttpSpinnerInterceptor (or HttpSpinnerInterceptor is not needed...), because it does not transform anything.
promise parameter is a $q promise that could be used in case if you need to perform some async actions when with result of your request as you can resole it later, so caller would get result later. Actually in your code, you directly resolve this promise (or reject it), changing src attribute of the image.
Here are some links to documentation:
Using $http service: http://docs.angularjs.org/api/ng.$http - take careful look at "Response interceptors" and "Transforming Requests and Responses"
Promises in AngularJS: http://docs.angularjs.org/api/ng.$q

Resources