I'm very new to Angular, so it's perfectly possible I made some stupid mistakes.
What I'm trying to do is use a token that is saved in localStorage and put that in all requests.
I have this code block:
.config(['$httpProvider', 'localStorageService', function($httpProvider, localStorageService) {
//Http Interceptor to check auth failures for xhr requests
$httpProvider.interceptors.push('authHttpResponseInterceptor');
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.headers.common.Authorization = 'Token token=' + localStorageService.get("TemponiaToken")
}])
And I'm getting this error message:
Uncaught Error: [$injector:modulerr] Failed to instantiate module starter due to:
Error: [$injector:unpr] Unknown provider: localStorageService
I found this question and answer which (I think) explains the problem: Why can't I use the localStorage in my .config when it's include in the .module definition?
However: how can I solve this? Change the .config into .run ? Thanks for any pointers in the right direction.
As the answer you found says is not possible to inject services during the config phase.
There are two possible solution to your problem.
The first one is to use the native localStorage object
localStorage.getItem("TemponiaToken") // it just works without injecting any service
The other one is to correctly define the interceptor
yourApp.factory('AuthInterceptor', function (localStorageService) {
return {
request: function (config) {
config.headers = config.headers || {};
config.headers.Authorization = 'Token token=' + localStorageService.get("TemponiaToken")
return config;
}
};
});
yourApp.config(function ($httpProvider) {
$httpProvider.interceptors.push('AuthInterceptor');
});
The documentation of ngStorage says thus:
Usage from config phase
To read and set values during the Angular config phase use the .get/.set functions provided by the provider.
var app = angular.module('app', ['ngStorage'])
.config(['$localStorageProvider',
function ($localStorageProvider) {
$localStorageProvider.get('MyKey');
$localStorageProvider.set('MyKey', { k: 'value' });
}]);
Related
This question already has answers here:
AngularJS Error: $injector:modulerr after being minified
(3 answers)
Closed 3 years ago.
I have the following .config code:
angular.module('app').config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(JSONInterceptor);
}]);
JSONInterceptor is just a simple function:
function JSONInterceptor($q, localStorageService) {
const API_URL = 'http://localhost:3000';
return {
request: function (config) {
const url = config.url;
// ignore template requests
if (url.includes('.html')) {
return config || $q.when(config);
}
if (localStorageService.get('use-json-server')) {
config.url = API_URL + config.url;
}
return config || $q.when(config);
}
};
}
The issue I am experiencing is that when I run the app in its non-minified form, everything works as expected. However, when I minify the app, I get an error for a seemingly unrelated service (though I guess they are related in the sense that they both touch $http):
Error: $injector:unpr
Unknown Provider
Unknown provider: eProvider <- e <- $http <- $uiRouter
I assume that this error has something to do with using a non-angular function as the interceptor (i.e., it is not a .provider or a .factory etc.), but I am not sure, and my attempts to make JSONInterceptor a provider have failed thus far. I know that .config has restrictions as to what can be included. However, even if this is the issue, I am having trouble understanding why it works unminified - I would assume that the same restrictions would apply to minified and unminified code.
Most likely the issue happens because of the dependencies injected in the interceptor ($q, localStorageService) as they are missing annotations.
To resolve this issue, try to register the interceptor as a factory as follows:
angular.module('app').config(['$httpProvider', '$provide', function($httpProvider, $provide) {
$provide.factory('JSONInterceptor', ['$q', 'localStorageService', function ($q, localStorageService) {
const API_URL = 'http://localhost:3000';
return {
request: function (config) {
const url = config.url;
// ignore template requests
if (url.includes('.html')) {
return config || $q.when(config);
}
if (localStorageService.get('use-json-server')) {
config.url = API_URL + config.url;
}
return config || $q.when(config);
}
};
}]);
$httpProvider.interceptors.push('JSONInterceptor');
}]);
I'm trying load this json file from remote url. In the beginning I was using $http.get function, but I was getting the next error message:
CORS 'Access-Control-Allow-Origin'
Now I am using JSONP, but nothing happens.
service.js file:
angular.module("elcomaApp").factory('ElcomaService', ['$http', function($http){
return $http({
method: 'JSONP',
url: 'http://vagalumewifi.com.br/timeline.json'
}).success(function(response){
return response.data;
}).error(function(err){
return err;
});
}]);
controller.js file:
angular.module("elcomaApp", []).controller('MainController', ['$scope', 'ElcomaService', function($scope, ElcomaService){
$scope.name = 'Natanael Santos';
console.log($scope.name);
ElcomaService.success(function(data){
$scope.elcomaData = JSON.parse(data);
var i = 0;
for (x in $scope.elcomaData){
console.log(i);
i++;
console.log(x.date);
}
}).error(function(data){
console.log(data);
});
}]);
app.js file:
var app = angular.module("elcomaApp", ['ngMaterial', 'ngRoute']);
I already hava read a lot of articles on stackoverflow, but no one work for me.
I'd suggest using $http.jsonp(url) method:
angular.module("elcomaApp").factory('ElcomaService', ['$http', function($http) {
$http.jsonp('http://vagalumewifi.com.br/timeline.json')
.success(function(data) {
console.log(data); // you can't `return` here...
}).error(function(err){
console.err(err);
});
}]);
Note: be warned that you can't expect that return in an async method has the same behavior as in a sync environment... :-)
Your original error is your clue. The endpoint server won't allow access from another domain.
CORS: Cross Origin Requests
You need to allow access on the endpoint server for the type of HTTP method you want to use (i.e. GET, POST, HEAD, ...) Additionally depending on what you're doing you may need to allow for an OPTIONS request, see Preflighted Requests in the MDN documentation above.
If you don't have access to that server you may need to do a work around by making $http call a script on your server that will fetch the file for you. I've done this before using PHP as a proxy and using PHP's file_get_contents function to grab files from other servers of a different domain.
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
}
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')
I wanted to add an interceptor to my module.
Here is the intial state:
app.config(function ($stateProvider, $urlRouterProvider,RestangularProvider) {
RestangularProvider.setBaseUrl('/app/services');
});
I modified with this:
app.config(function ($stateProvider, $urlRouterProvider, RestangularProvider, RestangularConfigurer) {
RestangularProvider.setBaseUrl('/app/services');
RestangularConfigurer.addFullRequestInterceptor(function (element, operation, route, url, headers, params, httpConfig) {
if (operation === 'get'){
console.log("RestangularProvider: call to get");
params.ts= new Date();
}
return {
element: element,
headers: headers,
params: params,
httpConfig: httpConfig
};
});
});
However, I add an error:
Error: [$injector:unpr] Unknown provider: RestangularConfigurer
So I replaced RestangularConfigurer by RestangularProvider.
But I do not clearly understand how that works, and what's happening behind the scenes.
Could you explain me that ?
First of all there is no RestangularConfigurer module. You have only Restangular and its provider RestangularProvider.
Let's start with angularjs documentation for providers.
Please esspecially read Provider Recipe as I do not duplicate it again here.
As a summary RestangularProvider is just a recipe how Restangular api should be build as you decide it in config module there is no Restangular api yet, but you have your recipe.
On the other hand Restangular will be bootstraped after your main module bootstraped, so in config there is actually no Restangular module yet.
If you still insist using Restangular instead its provider you can use it in module#run instead of module#config.