I am trying to send a header which each HTTP for a ngResource (auth token in this case)
This somewhats works :
app.factory('User', ['$resource','$window',
function($resource,$window,liftHost, liftBasePath) {
return $resource('/api/users/:id',{},{
get: {
method: 'GET',
headers: {'token': $window.sessionStorage.token}
}
});
}]);
The problem with this code, is that after the first call, each GET request will have the same header value. It does not get re-evaluated. So if a users logs out, and then log backs in, this will change the value of $window.sessionStorage.token, but the request will be sent using the previous value of the token.
I have created a small plunker with $httpBackend mocks to illustrate it.
see : http://plnkr.co/edit/xYZM6wlDJ6CH2BPHLZAC?p=preview
Here is a Plunker with this working
I introduced a TokenService that is injected into the User and Session services. This is a bit cleaner than depending on the $window service. Also, I made the token an object rather than a primitive string. This allows the token to be passed around by reference rather than value.
app.factory('Token', [
function() {
return {
value: "a"
}
}
]);
Related
I want to send an api key for every request I make:
function MyService($http) {
var req = {
method: 'GET',
url: 'https://api.giphy.com/v1/stickers/trending',
headers: {
'api_key':'123'
}
}
return $http(req);
}
but the problem is that all requests are OPTIONS (not GET) and is not sending the api_key. Is that the right way to send headers? thanks
Editing because it was marked as duplicate:
This is not a CORS issue. The error I´m getting is 401. That means authentication failed because the endpoint is not receiving the request header with the api_key.
What you did is totally fine, but if the api_key is always different, so you have to provide the api_key value dynamically in order to be added to the request.
If it is always the same, you have a really better way to do that: through interceptors. And you will set that only one time. Again, this method is if you have to set up some parameter which is always the same, so actually it is for doing standard operations over HTTP requests.
First, you need to define your Interceptor:
myApp.service('MyRequestsInterceptor', [function() {
this.request = function(config) {
config.headers.api_key = 'My Default API KEY';
return config;
};
}]);
And then simply add your interceptor to AngularJS $httpProvided:
myApp.config([ '$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push('MyRequestsInterceptor');
} ]);
I am new to Angularjs and wondering how to check the token's expire date and time before sending any request.
I googled and found there are concepts like interceptors and decorators in angular but I am a bit confused which one to use and how. Or is there any better way to do it.
What am I doing right now?
I have created a service that has GET, POST functions take url, data and config as parameters and there I am checking the token. I know this is not the right approach.
You can use an interceptor that will configure every $http call. enter link description here
You can write interceptor which will cancel invalid token request before it is actually sent:
return {
'request': function(config) {
if (condition) {
var canceler = $q.defer();
config.timeout = canceler.promise;
canceler.resolve();
}
return config;
}
}
Obviously, you can manipulate config before returning it and (for example) change token.
I am trying to communicate with some REST API that works with some kind of token system. The way it is supposed to work is that when I POST to /api/login with a user/pass then I get a token back. Then on subsequent request I should add a X-Auth-Token header with the token and then in the response I will get an updated token. So I figured I could use an interceptor for this, something like below:
app.config(['$httpProvider','AppConfig', function($httpProvider,AppConfig) {
$httpProvider.interceptors.push(['$q', '$injector', function($q, $injector) {
return {
'request': function(config) {
// add token header only if request is not initial token request
if (!config.url===AppConfig.serverUrl+'/api/login') {
config.headers['X-Auth-Token'] = $injector.get('$window').localStorage.getItem('token');
console.log(config);
}
return config;
}
}
}]);
}]);
When I run the code, I get the token from the API correctly, it gets saved to the localStorage and then, due to the console.log, I see that on the subsequent request the interceptor adds the X-Token-Auth header to its config.
However, I guess when the actual request is being composed by Angular, it complains about:
Failed to execute 'setRequestHeader' on 'XMLHttpRequest' : "<token>" is not a valid HTTP header field value.
The headers look like this:
Accept: "application/json, text/plain, */*"
X-Auth-Token: "Sl6J/xTGXteGwDK/BYt5/FWrrkvSHsz1wFbHlfHNsO7vo1keZad35tHjHansMTwm"
The only real difference I see here with when I try something similar in the Chrome postman extension, is that postman sends the token without quotes whereas Angular sends them with quotes around the token.
I guess it would be best if the server would be able to cope with that, but since I don't have control over it, is there a way to remove those quotes?
Thanks!
i faced the same problem, so i removed qutotes from start and end:
localStorage.getItem('token').replace(/^"(.*)"$/, '$1')
We are integrating Google App State into our web based game using Google's API discovery service. Our test code looks like this:
gapi.client.load('appstate','v1',function(response) {
var request = gapi.client.appstate.states.update({ stateKey: 0 });
request.execute(function(result) { console.log(result); });
});
I always get back an HTTP 400 with the message "The update request does not contain any data.". This makes sense since I'm not passing any data, the problem is that I have no idea how to pass the data (aka state) and I can't find any documentation on how to do it. I tried passing some data along with the stateKey
{ stateKey: 0 , data: <some-base64-encoded-data> }
But this still fails with the same message.
After inspecting the library's minified code I'm starting to suspect this feature is still unimplemented.
UPDATE (after doing some more experiments)
I also tried using gapi.client.request like this:
var request = gapi.client.request({
'path': '/appstate/v1/states',
'params': { 'stateKey': '0' },
'method': 'PUT',
'body': {
'kind': 'appstate#updateRequest',
'data': 'ZGF0YQ=='
}
});
But I get a 404 and I think it's because this method passes request parameters in the &stateKey=0 style. On the other hand if I use 'path': '/appstate/v1/states/0' I get a conflict response which is what I was expecting.
Correct me if I'm wrong but I'm starting to believe that the problem is due to inconsistencies between Google's different web APIs which they are now trying to coalesce into a single interface.
In your initial Discovery-based method, you need to pass the data in a parameter named 'resource.'
Here is the Discovery document for appstate/v1: https://www.googleapis.com/discovery/v1/apis/appstate/v1/rpc
In my factory
return $resource('rest/records/:id', {}, {
query: {
method: 'GET',
isArray: true,
// RestSQL has an extra struct around the array
transformResponse: function(data) {
return angular.fromJson(data).records;
}
},
create: { method: 'POST' },
update: { method: 'PUT', params: {id: '#id'},
});
Which is used by a service which is in turn used by a controller.
I get the correct record in the controller.
Then when I edit and want to save the record
I do record.$update();
my rest POST is successful as I get a valid response from server.
But the response from server is just some kind of success message e.g. "{ "number": 2 }".
Now I have an angular template which uses this records properties e.g. {{record.image}}
But as soon as I do record.$update();
records properties disapper and record now simply looks like
record = {"number" : 2}
So should I return the entire record as a response to the POST action or should I update in some other fashion so as to the record doesnt get its properties overwritten by the response from server?
A temporary way of getting around this of course is
$scope.temp = jQuery.extend(true, {}, $scope.record);
$scope.temp.$update();
I am returning the updated object on POST's, PUT's etc. (see also this: Should a RESTful 'PUT' operation return something) all the time. So,
no problem with always returning the updated object in the response
don't use tricks and more code to sove a problem that can be solved by applying a very simple solution (in this case, returning the updated object). I love those fixes: Simple solution, problem solved and code removed instead of adding things here and padding things there etc., making code unreadable und unnecessarily complex.