How can i set default param in ngResource to be POST - angularjs

I have a simple AJAX request that needs a csrf token for every call and i define it like so:
app.factory('auth', ['$resource', '$cookies', function($resource, $cookies){
var getCsrf = function() {
//get csrf token from cookie
};
return {
login: $resource('auth/login', {}, {
'q' : {
method: 'POST',
params: {csrf_token: getCsrf()}
}
}),
// ... some more requests
};
}]);
As i understood it you can specify the default url parameters as second param of the $resource()-call, in my case the empty object {}. Apparently the data i set in the configurations object under params: ... also gets send via GET and not with the specified POST-method.
One way would be to manually put the csrf_token in where i make the call to the api-function, but i'd like to keep it clean. Is there a way to tell angular what method to use for the default params? So i could simply use ..
auth.login.q(email, password, ...).then( ... );
.. without having to implement the csrf-getter function into all my calls. Also i am relatively new to AngularJS so a simple answer would be great!

There is an easy way to this in angular:
set the xsrf cookie name and header name defaults in the config module.
app.config(['$httpProvider', function($httpProvider) {
// response cookie name
$httpProvider.defaults.xsrfCookieName = 'csrf_cookie';
// request header name where the value of the cookie get set
$httpProvider.defaults.xsrfHeaderName = 'HTTP_X_XSRF_TOKEN';
// to set ajax request header
$httpProvider.defaults.headers.common = { 'X-Requested-With' : 'XMLHttpRequest'};
}

Related

AngularJS $resource GET params appear in URL

My REST backend [ based on NodeJS/express/mongojs] is complaining 404 (not found) when Params are attached as part of URL. Backend rest interface is coded as below;
var express = require('express');
var router = express.Router();
router.get('/login', auth.signin); //auth.signin is code to verify user
Above REST service is consumed by AngularJS based frontend through $resource as below;
Definition:
angular.module('myapp').factory('signinmgr', function($resource) {
return $resource("http://localhost:3000/login", {}, {
'get': {
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
}});
Usage:
signinmgr.get({'username':'myname', 'password':'mypass'}, function(data){
//success
}, function(x){
//failed
});
Problem:
Frontend code above produces a URL to consume REST service where parameters are part of URL i.e. http://localhost:port/login?username=myname&password=mypass [if I use GET method, POST is OK]. I wanted my front end to keep URL as http://localhost:port/login and post any parameters through body as backend is using req.body.paramName to read those. [Actual Solution]
If (1) cannot be done, and my frontend is sending params as part of URL, I needed help as to know how to equip my backend to allow this URL with parameters so that backend doesnt return 404 as the base URL http://localhost:port/login is already there.
PS: for (1), I tried this thread with data:{username:'',password:''} but of no use. Please help if I am missing something very obvious or some concept.
Try the $http service instead:
angular.module('myapp').factor('signinmgr', function($http) {
return {
login: function (username, password) {
$http.post("http://localhost:3000/login", {
username: username,
password: password
}
}
};
});
signinmgr.login('myname', 'mypass').then(function(data){
//success
}, function(x){
//failed
});
Each request that my nodejs/expressjs backend receives has three places for passed attributes;
params{}
query{}
body{}
My problem (1) cannot be fixed in case I want to use GET method since with GET request parameters are visible as part of URL i.e. http://localhost:port/login?username=myname&password=mypass. To send my username/password I had to use POST that sends parameters as part of body{}.
My problem (2) was that I was using GET and mistakenly looking for parameters in body{} of request. Instead, parameters passed as part of URL in GET request are added to query{} of the request.

API-key header is not sent (or recognized). Angularjs

I'm trying to access an API with AngularJS but I get the following error:
XMLHttpRequest cannot load http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://purepremier.com' is therefore not allowed access.
This is my code for the service:
angular.module('PremierLeagueApp.services', []).
factory('footballdataAPIservice', function($http) {
var footballdataAPI = {};
footballdataAPI.getTeams = function() {
$http.defaults.headers.common['Auth-Token'] = 'token';
return $http.get('http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK');
};
return footballdataAPI;
});
I use an authentication token (api key) to access the api, but according the API owner this API key header is not sent or recognized. Do you have any idea how I can adapt the code to make this work? thanks!
You should hide that API key before posting on a public site such as this. I would advise you regenerate your key (if possible) just in case - better safe than sorry.
Assuming your site url is 'http://purepremier.com' from the error message, the API should add a 'Access-Control-Allow-Origin' header with your site URL to allow you access. Have a look here for more information.
This is not directly related to your problem, but I notice you are setting $http defaults every time getTeams() is called. You should either set this outside of the actual function call (preferably in a run block), or just send the GET request with that header specifically applied. As the API key is specific (I assume) to that call, you may not want to be sending it to anyone and everyone, every time you make a HTTP request.
Change your factory code like this:
factory('footballdataAPIservice', function($http) {
return {
getTeams: function(){
return $http({
url:'http://www.football-data.org/alpha/soccerseasons/398/leagueTable',
headers: { 'X-Auth-Token': 'your_token' },
method: 'GET'
}).success(function(data){
return data;
});
}
}
});
Inject factory in your controller and retreive the data:
.controller('someController',function(footballdataAPIservice,$scope){
footballdataAPIservice.getTeams().then(function(data){
$scope.teams=data;
console.log($scope.teams)
});
});
Here is the working plunker
You change the Auth-Token To Authorization
$http.defaults.headers.common['Authorization'] = 'token';
Because token is send via headers using Authorization
try jsonp
angular.module('PremierLeagueApp.services', []).
factory('footballdataAPIservice', function($http) {
var footballdataAPI = {};
footballdataAPI.getTeams = function() {
$http.defaults.headers.common['Auth-Token'] = 'token';
return $http.jsonp('http://www.football-data.org/alpha/soccerseasons/398/leagueTable?callback=JSON_CALLBACK');
};
return footballdataAPI;
});

Angularjs: Set a custom header on $resource before an action is called?

I have the following $resource definition:
angular.module("MyApp").factory("account", ["$resource",
function ($resource) {
var userResource = $resource("http://localhost/api/account/:id",
{
id: "#id"
},
{
register: {
method: "Post",
}
);
return userResource;
}]);
Before each call to user.query, get, register, etc... I need to set a custom header which is an authorization header with an access token.
Please note that setting the header globally would not work, because the access token might expire and be refreshed with a new one before every call to the $resource and therefore the authorization header will change. Also I need to set the header only on specific actions. For example I do not need it on the save action.
I read this article:
http://nils-blum-oeste.net/angularjs-send-auth-token-with-every-request/
which by the way is linked on several stackoverflow posts. But this is not what I need as it sets the token in the data of the action and I need it in the header.
for me, this was just a syntax problem - this post helped me out.
Dynamic Resource Headers
.factory("ResourceService", function() {
return {
Token: function(token){
return $resource("someurl/checktoken", {}, {
validateToken: {method:"POST", params: {}, headers: {"MY-AUTH-TOKEN": token}}
});
}}})

AngularJS ngResource not sending custom header

I'm attempting to use ngResource to query a REST API. I need to specify my API key in a custom header. I've tried it like so:
angular.module('ApiService', ['ngResource'])
.factory('Api', ['$resource', function($resource) {
this.apiEndpoint = '';
this.apiKey = '';
return {
init: function(apiEndpoint, apiKey) {
this.apiEndpoint = apiEndpoint;
this.apiKey = apiKey;
},
get: function(collection) {
return $resource(this.apiEndpoint + 'api/1/' + collection, {},
{
get: {
method: 'JSONP',
headers: {'api_key': this.apiKey},
params: {callback: 'JSON_CALLBACK'}
}
}
).get();
}
};
}]);
which I then use in my controller like:
app.controller('MyCtrl', function ($scope, Api, ENV) {
Api.init(ENV.apiEndpoint, ENV.apiKey);
var widgets = Api.get('widgets');
});
My custom header isn't set when I inspect the XHR. Also, why will the XHR not run until I call an empty .get() after the initial $resource:get() method?
I've also tried to set the headers in $httpResource directly:
.config(function($httpProvider) {
$httpProvider.defaults.headers.get = {'api_key': 'abc123'};
})
but this still doesn't set the custom header when I inspect the network request. What am I missing?
This issue is, of course, that I was using JSONP in this request, which doesn't include the ability to craft headers when making a request. See how to change the headers for angularjs $http.jsonp.
Specifically, JSONP simply includes a <script> tag at the bottom of the DOM to load cross-domain javascript, so it's up to your browser to send the default headers.

Patch request with angular.js is send to wrong url

My REST API is configured to accept this kind of request
public function lockUserAction($slug)
{} // "lock_user" [PATCH] /users/{slug}/lock
So sending a patch request to
/api/users/2/lock
Will lock the user with id=2. This is my rest service inside angular.js
angular.module('UserService',['ngResource']).factory('User', function($resource){
var User = $resource('/api/users/:id',
{},
{
list: { method: 'GET' },
lock: { method: 'PATCH' }
}
);
return User;
});
List works just finde, but lock does not work. The console prints:
PATCH /api/users 405 (Method Not Allowed)
I invoke it like this
$scope.lock = function(user){
user.$lock();
}
In the error message I see the url /api/users instead of /api/users/2/lock. Is this normal behaviour? Of course list excepts only GET requests and PATCH requests are not allowed on /api/users only on /api/users/{slug}/lock.
Any ideas why /api/users is called and not /api/users/{slug}/lock. Any ideas how to fix this?
When you call $lock angular has no idea that you intend to call the same url as before, with some extra path element. Also there is no way for angular to know what is a value of :id param.
Than let angular know about locking:
var User = $resource('/api/users/:id/:action', //add param to the url
{},
{
list: { method: 'GET' },
lock: { method: 'PATCH',params:{action:"lock",id:"#id"}} //set param value, so angular knows where to send request, #id refers to user id in json representation of user
}
);

Resources