ngResource custom headers when calling action - angularjs

In ngResource action I can specify custom request headers. However I need to set the headers at the time of calling the resource action.
The reason is I need paging and sorting data for the list query, and those need to be specified by custom headers (X-Order, X-Offset, and so on). This data can vary from call to call, so I cannot have them in the resource action definition.
Is there a way to pass headers while calling the action? (other than setting $http defaults)

Try Restangular service.
You can find there method: setFullRequestInterceptor which may fit your needs
//From Documentation
RestangularProvider.setFullRequestInterceptor(function(element, operation, route, url, headers, params, httpConfig) {
return {
element: element,
params: _.extend(params, {single: true}),
headers: headers,
httpConfig: httpConfig
};
});
Examples: http://plnkr.co/edit/d6yDka?p=preview

Related

Angular: set Content-Type per query

I need to perform one query with Content-Type different than application/json.
Changing default $http options is not a variant, because a lot of queries still be performed with JSON data.
I've found example
var req = {
method: 'POST',
url: 'example.com',
headers: {
'Content-Type': "application/x-www-form-urlencoded"
},
data: "somedata"
}
$http(req).then(function (resp) { console.log(resp);});
But it don't want to work — Content-Type is still a application/json.
Is any true way to do it right? Changing $http defaults and then restoring is not a solution.
What you are doing is not a valid way to set headers in angularjs.
To add or overwrite these defaults, simply add or remove a property
from these configuration objects. To add headers for an HTTP method
other than POST or PUT, simply add a new object with the lowercased
HTTP method name as the key, e.g. $httpProvider.defaults.headers.get =
{ 'My-Header' : 'value' }.
Ref. https://docs.angularjs.org/api/ng/service/$http - "Setting HTTP Headers" section
Edit.
What you're doing is right but you're missing one thing.
In your scenario it does not work because when using application/x-www-form-urlencoded you need to encode your data using $httpParamSerializerJQLike(). Also remember to put $httpParamSerializerJQLike as dependency.

AngularJS - Setting default http headers dynamically

To overcome csrf attack, I have to send in csrf-token value in a header for every request by picking in the value from cookie as described here. Since this is to be done at every request, I am setting the default headers for $http in the main module's run function.
Now, If a new tab is opened for the same website, a new csrf token (in cookie) is issued by the server. Since the run function is run only once, the default header for csrf will be old one (for old tab), while the new csrf cookie will be sent to server, resulting in csrf-mismatch.
How to overcome this at a global level?
I want somehow to create a function which will be run everytime the $http is called, so that then I'll override the default headers.
Note: I do not want to set this header value for every $http request.
(Not that I think that it's relevant, but I'm using ui-router)
Edit
This is not just limited to csrf-token, I want to set some other headers too based on the logged in user, which has to be done dynamically (say when one user logs in, and logs out, then another user logs in).
you need to use http interceptor to do this on every request. read more about http interceptors here
below is one such example
module.factory('xsrfTokenInterceptor', function ($q, $http) {
return {
'response': function (response) {
var cookies = response.headers("Set-Cookie");
var token = someCrazyParsing(cookies);
$http.defaults.headers.common["X-CSRFToken"]=token;
return response || $q.when(response);
}
};
});
module.config(function($httpProvider){
$httpProvider.interceptors.push('xsrfTokenInterceptor')
})
How about headers $http(config) parameter.
$scope.getWithHeader = function(){
$http({
method: 'GET',
url: 'http://fiddle.jshell.net',
headers: {
'CustomHeader': 'HelloWorld'
}
}).success(function(){
console.log("success");
});
};
sample code on jsFiddle

When do we use .$put instead of .put on an angular resource?

Say, I have the following resource:
angular.module('app.resources.demo-resource', ['ngResource'])
.service('demoResource',
function ($resource) {
return $resource('/api/path', { }, { put: { method: 'PUT' } });
});
and I want to invoke the put request, using promises later.
How do I do it correctly?
newResource.$put().then(...) or newResource.put().then(...)?
Does both variants exist and what is the difference between them?
When you define a "non-GET" action (basically, one with a method that has a request body: PUT, POST, PATCH), ngResource will automatically create corresponding actions/methods on every instance of that resource (prefixed by $). This is just for convenience.
Basically, you have two ways to call such an action:
<Resource>.action([parameters], postData, [success], [error])
or
<instance>.$action([parameters], [success], [error])
The benefit of the latter is that you don't need to specify the postData (it's the <instance> object that acts as the data).
With promises: (To the answer of #ExpertSystem)
<Resource>.action([parameters], postData).$promise
or
<instance>.$action([parameters])
is automatically a promise. The first approach looks more stable in practice. (Angular resolved an instance to the wrong resource after I did _.extend({}, resource))

How to pass body payload to angular $resource DELETE call

I have standard angular $resource configured as such
angular.module('client.resources')
.factory('ProjectSubjectResource',['$resource',
function ($resource) {
release: {
method: 'DELETE',
isArray: false
}
});
}]);
and I am calling this method as
ProjectSubjectResource.release({projectId: projectId, subjectId: 0},{ subjectIds: subjectIdArray})
where subjectIdArray is array of objects:
[{subject1: 213123}, {subject2: 3131}]
However, body of request does not contain that array. I suspect that DELETE request is the problem, as renaming method call to e.g. PUT makes difference.
Can I allow body of DELETE request somehow?
Take a look at this answer.
The body of a request for a DELETE is ignored. You will have to use POST to do what you want, or describe the data you are sending with the URL.
UPDATE: DELETE requests can have a body since Angular 1.6.4; check denisazevedo's answer for additional info.
Starting on Angular 1.6.4, the hasBody action configuration was added.
You can now have:
deleteSomething: {
method: 'DELETE',
hasBody: true
}
hasBody - {boolean} - allows to specify if a request body should be
included or not. If not specified only POST, PUT and PATCH requests
will have a body.
Reference

How do I remove the default headers just for specific XHR requests in AngularJS?

99% of my ajax calls need a specific "X-API-TOKEN" to authenticate and communicate with my Rails REST API. But I'm also making a call to one thrid party API and I keep getting an error saying "Request header field X-API-TOKEN is not allowed by Access-Control-Allow-Headers."
Everything works fine if I delte the header right before the call, and a work around would be to delete and then re-add after the call, but is there an easier way than this:
apiToken = $http.defaults.headers.common["X-API-TOKEN"]
delete $http.defaults.headers.common["X-API-TOKEN"]
$http(
method: "GET"
url: 'http://...}}'
).success((data, status, headers, config) ->
).error (data, status, headers, config) ->
$http.defaults.headers.common["X-API-TOKEN"] = apiToken
Set the desire header/headers to undefined like this, then it will not affect the global settings.
$http( {
method: 'GET',
url: 'someurl',
headers: {
'X-API-TOKEN': undefined
}
}
)
The $http service config object allows you to override the http header send for a specific request. See config property headers.
This can take a list of headers or a function that return a list of headers. So for the non auth header request make a copy of the default headers remove the header you dont require and then make the request. You can store this for later use.
See $http documentation

Resources