add config in angular resource - angularjs

I am using http-auth-interceptor for authentication. In http-auth-interceptor, I use the following way to login:
var data = 'username=' + encodeURIComponent(user.userId) + '&password=' + encodeURIComponent(user.password);
$http.post('api/authenticate', data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
ignoreAuthModule: 'ignoreAuthModule'
})
ignoreAuthModule is used to tell ignoreAuthModule that this login method will be ignored by the auth interceptor.
Now, I have some request with $resource, like:
.factory('SomeDataService', function ($resource) {
return $resource('api/some/data', {}, {
'get': { method: 'GET'}
});
})
I want SomeDataService.get() is also ignored by the auth interceptors, because I need to control the 401 error by myself.
So, my question is, is there any way for ngResource that I can set config like that in $http.
[update based on comment]
I have listened the login-required event:
$rootScope.$on('event:auth-loginRequired', function (rejection) {
$log.log(rejection);
// I need to get the request url and for some specific url, need to do something.
$rootScope.loginPopup();
});
But the 'rejection' parameter has no context data of request I need. I need to get the request url and check, for some specified url, I need to do something.

After checking the document of ngResource, I got the solution as below:
.factory('SomeDataService', function ($resource) {
return $resource('api/some/data', {}, {
'get': { method: 'GET', ignoreAuthModule: 'ignoreAuthModule'}
});
})
Just add the config item as above. It will be equivalent ad:
$http.post('api/some/data', data, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
ignoreAuthModule: 'ignoreAuthModule'
})

ngResource module is build on top of $http.Hence it is not possible to configure all the stuffs you can do with $http in $resource.I think the below link will be guide you to have a clear understanding on $http and $resource

Related

Can't include header in `$http` angular

I got a token from backend which I saved it in $sessionStorage and I need to include that along with $http request that I call. I tried include it directly but when I checked it from backend, it's not there.
function _selectGender($sessionStorage, gender) {
return $http({
method: 'POST',
url: config.apiURL + '/auth/gender',
headers: {
'Authorization': $sessionStorage.token
},
data: {
gender: gender
}
}).then(updateCompleted).catch(updateFailed);
}
I also tried with interceptor which it's not working as well.
requestInterceptor.inject = ['$sessionStorage'];
function requestInterceptor($sessionStorage){
return {
'request': function(config){
if ($sessionStorage.token) config.headers['authorization'] = $sessionStorage.token;
return config;
}
}
}
Shoot me some idea how to tackle this. :D
Edit#1: It's likely possible to be preflight error
It's actually because of OPTIONS headers, seem like $http will send a pre-request before browser send an actual request to backend. You need to handle that from the backend. Thanks #Nitish Kumar's comment.
Read more about cors
How to handle OPTIONS

Angular: $http change method on adding data with post

I am using fuse template and accessing my web service by using $http, its working fine if i am using method: 'POST' without send any data but whenever i am adding some data with post like: data: {text:'test'} and send request to my web service its change the method type POST to OPTIONS.
My Code:
$scope.submit = function(){
$http({
method: 'POST',
url: 'http://www.example.com/api-link',
data: {test: 'hello'},
header: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(result){
console.log(result);
});
}
When i am checking in browser network its showing method type OPTIONS. Can anyone please tell what is wrong in my code?
Thanks

AngularJS 1.3 to 1.5 transformRequest broke, solution for my specific situation?

Long story short. I am really not an AngularJS guru. Our site upgraded from 1.3 to 1.5. This one thing is breaking.
We used to inject an HTTP header via transformRequest in a factory named 'api':
.factory('api', function($resource) {
function add_auth_header(data, headersGetter) {
var headers = headersGetter();
headers['Authorization'] = ('Basic ' + btoa(data.username +
':' + data.password));
}
// defining the endpoints.
return {
auth: $resource('/api/v1/auth/', {}, {
login: {method: 'POST', transformRequest: add_auth_header},
logout: {method: 'DELETE'},
}),
Later on in the same file, this is called like so:
.service('auth', function($cookies, $rootScope, api) {
this.user = null;
this.login = function(credentials) {
var log = api.auth.login(credentials);
log.$promise.then(function(data){
// on good username and password
this.user = data;
});
As you can see, it calls api.auth.login with the credentials. I have verified that the transform request is being called, the headers are being fetched properly by headersGetter(), and that hanging the headers[] object no longer changes it like it used to in 1.3. Fiddler verifies that the request no longer has an Authorization header in it like it did in 1.3, and the Django server that gets the request also agrees.
I've read in a few places that the transformRequest functionality 'broke' in 1.4, but those posts have always been in the context of making an $http request, not providing an api service through a factory, and haven't made much sense to an AngularJS newb like me. I have no idea where I would start changing how Authorization is injected.
Can anyone point me the right way?
If anyone else is still facing this, the change was under breaking changes in the changelog for 1.4.
I feel the fix speaks for itself. Note that the function add_auth_header is not invoked but rather is passed.
.factory('api', function($resource) {
function add_auth_header(data) {
// as per HTTP authentication spec [1], credentials must be
// encoded in base64. Lets use window.btoa [2]
return 'Basic ' + btoa(data.data.username + ':' + data.data.password);
}
// defining the endpoints.
return {
auth: $resource('/api/v1/auth/', {}, {
login: {method: 'POST', headers: { 'Authorization': add_auth_header }},
logout: {method: 'DELETE'},
}),

Set defaults header on AngularJS but don't use it on one specific request

For sending OAuth2 token I am setting up defaults header on AngularJS like this:
$http.defaults.headers.common['Authorization'] = 'Bearer ' + access_token;
This works great but I don't need this header (I get an error) for one specific request.
Is there a way of excluding defaults header when performing that request?
Thanks!
SOLVED
Thanks to Riron for getting me on a right path. Here's the answer:
$http({
method: 'GET',
url: 'http://.../',
transformRequest: function(data, headersGetter) {
var headers = headersGetter();
delete headers['Authorization'];
return headers;
}
});
When you make your call with $http, you can override defaults headers by providing them directly in your request config:
$http({method: 'GET', url: '/someUrl', headers: {'Authorization' : 'NewValue'} }).success();
Otherwise you could transform your request using the transformRequest parameter, still in your $http config. See doc :
transformRequest – {function(data,headersGetter)|Array.<function(data, headersGetter)>} – transform
function or an array of such functions. The transform function takes
the http request body and headers and returns its transformed
(typically serialized) version.
This way you could delete an header for a single request before it's being send:
$http({method: 'GET',
url: '/someUrl',
transformRequest: function(data,headersGetter){ //Headers change here }
}).success();
For latecomers, whilst the solution might have worked - you actually shouldn't need to use transformRequest for this.
The Angular docs for the $http service actually have this exact situation covered:
To explicitly remove a header automatically added via
$httpProvider.defaults.headers on a per request basis, Use the headers
property, setting the desired header to undefined.
For example:
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': undefined
},
data: {
test: 'test'
}
}
$http(req).success(function(){...}).error(function(){...});
Angular 1.4.0 can no longer modify request headers using transformRequest:
If one needs to dynamically add / remove headers it should be done in
a header function, for example:
$http.get(url, {
headers: {
'X-MY_HEADER': function(config) {
return 'abcd'; //you've got access to a request config object to specify header value dynamically
}
}
})
While the $httpProvider can override $http the use of intereceptors are 1 way of handling this, I end up doing it this way
function getMyStuff(blah) {
var req = {
method: 'GET',
url: 'http://...',
headers: {
'Authorization': undefined
}
}
return $http(req)
.then(function(response) {
return response.data;
});
}

$resource invalidation in angularjs

I have this use case where I pass authToken to every request and this token changes everytime the person logins.
app.factory('Comment', function ($resource, localStorageService, $cacheFactory) {
return $resource('http://localhost:port/comments/:id', {"id":"#id", port:':9000'}, {
query: { method:'GET', isArray: true , headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
save: { method:'POST',headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
update: {method:'PUT' ,headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
delete : {method: 'DELETE',headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}},
get : { method: 'GET', headers: {'X-AUTH-TOKEN':'authToken='+localStorageService.get("authToken")}}
});
The behaviour I am seeing is that if the authToken changes for some reason the $resource keeps adding the previous authToken while sending the request. I am using the $http directly for login and for any commenting related stuff I am using $resource. Am I missing something?
After login I make sure that my localStorage has the newly created token but the request are using the previous authToken till I refresh the page after which it adds the correct header I know that the $resource uses some kind of caching and tried to remove the $http cache like this after loggin in.
$cacheFactory.get('$http').removeAll();
but didnt't help
It's because token is assigned once when factory code executes. Try this instead:
get : { method: 'GET', headers: {
'X-AUTH-TOKEN': function(){
return 'authToken=' + localStorageService.get("authToken");
}
}}

Resources