Overriding Angular $http post to extend every post data with additional data - angularjs

In Yii framework, we have to add a CSRF token to the POST data so that the request can be validated.
The token is generated by PHP and I'm passing the variable like this
angular.module('MyConstant', []).constant("MyConstant",
{'postdata': {'_csrf': 'ABCDEF'}}); //this is written by PHP
var app = angular.module('MyApp', ['MyConstant']);
app.controller('MyCtrl', [
'$scope', '$http', 'MyConstant',
function ($scope, $http, MyConstant) {
}]);
whenever I want to send POST, I have to do something like this.
$http.post(url, angular.extend(MyConstant.postdata, {data: mydata}));
The POST body will be something like this
{"_csrf": "ABCDEF", "data": "bla bla bla"}
I'm just curious if there is a "Angular way" to override the $http.post to automatically append the data to avoid code duplication like angular.extend(ViewConstants.postdata above.
UPDATE
Thanks to #GregL for the pointers. I can do it like this using interceptors
app.config(['$httpProvider', 'MyConstant',
function ($httpProvider, MyConstant) {
$httpProvider.interceptors.push(function () {
return {
request: function (config) {
if (config.method == "POST"){
config.data = angular.extend(MyConstant.postdata, config.data);
}
return config;
}
};
});
}]);

Yes, you should be able to register an interceptor.
Just add an interceptor for the request method, and check if the config.method === 'POST' and if so, add your constant to the data sent (config.data).

Related

sending headers using $resource in angular js

I want to send headers each time for CRUD operation from factory side.
Here is my factory
var appangular.module("LifeStyleFactModule",["ngResource"]);
app.constant("RES_URL", "http://localhost:9090/")
app.factory("CategoryFactory",function($resource,RES_URL){
var categoryinfo;
var categoryresource=$resource(RES_URL+"category/:id",{"id":"#id"},{update:{method:"PUT"}});
return{
getcategory:function(){
categoryinfo=categoryresource.query();
return categoryinfo;
},
addcategoryItem:function(categoryItem){
var category = new categoryresource(categoryItem);
category.$save(function(respdata){
categoryinfo.push(respdata);
},function(respdata){
});
},
deletecategoryItem:function(idx,id){
var category=new categoryresource({"id":id});
category.$delete(function(){
categoryinfo.splice(idx,1);
},function(){
})
},
updatecategoryItem:function(categoryItem,idx){
var category=new categoryresource(categoryItem);
category.$update({"id":categoryItem._id},function(data){
categoryinfo[idx]=data;
},function(){
})
}
}
})
the above functionality is working well. Now i want to send the token in the headers. How can i do that.
I have tried to do it by the following way
var categoryresource=$resource(RES_URL+"category/:id",{"id":"#id"},{update:{method:"PUT"},headers:{"token":"#token}});
but not getting how to send the token for CRUD operation.
Is procedure is correct, if so how can i send tokens.
Else let me know the way.
Instead of above method i tried the following way as
$resource(RES_URL+"category",{},{query:{method:"get",isArray:true,headers:{"token":token}}}).query({},function(res){});
this is working but the procedure for the first procedure.
Please after answering mark it as duplicate or down vote
dont say ( / { such things are missing.
The best solution as to me is to use interceptor. Here is a way to send token in headers, I've used in one of my projects.
angular
.module('app.core')
.config(config);
config.$inject = ['$httpProvider'];
function config($httpProvider) {
$httpProvider.interceptors.push(interceptor);
}
interceptor.$inject = ['$q', '$injector', 'AuthModel'];
function interceptor($q, $injector, AuthModel) {
return {
request: function (config) {
config.headers.Authorization = AuthModel.token;
return config;
},
responseError: function (rejection) {
}
};
}
Added a jsfiddle to demonstrate
https://jsfiddle.net/Sergey_Mell/c47js1zc/
Just click the Send button and check the request headers in developer tools

Maintain session using Interceptor cookies/ server-sessions

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
}

How to create a POST request in my case?

I am trying to make a POST request via $resource object in Angular.
I have something like
(function (angular) {
angular.module('myApp')
.factory('myService', [
'$resource',
function ($resource) {
var serviceObj = $resource('http://testProject/products/', {id: '#id'},{
'createItem' : {
url: 'http://testProject/item/:id',
method: 'POST',
params: {type: ‘#type'}
}
});
return serviceObj;
}
]);
})(angular);
in my controller
//omit the controller codes…
myService.type = ‘Detail’;
myService.createItem(function(data) {
console.log(data)
});
I see stuff back from the console.log but it has the wrong data because the type is shown as ‘Name’ instead of ‘Detail’. I know api supports that and I don’t see anything wrong with my service. Can someone help me out for it? Thanks a lot!
It looks like your are getting data back,
I would try:
console.log(data.data);
Since your are returning an object from your service.

Unable to create POST request to REST API with $resource in angularjs

I am learning about the MEAN stack, and have created a REST API which posts a review to a collection in MongoDB.
I have defined a service as given:
angular.module('myApp')
.constant('baseURL', 'http://localhost:8080/');
angular.module('myApp')
.service('addReviews', ['$resource', 'baseURL', function($resource, baseURL) {
this.getReviews = function() {
return $resource(baseURL+'reviews/', null, {'save': {method: 'POST'}});
};
}]);
Now, I am calling this service from my controller:
angular.module('myApp', ['ngResource'])
.controller('reviewController', ['$scope', 'addReviews', function($scope, addReviews) {
$scope.reviewSubmit = function() {
$scope.receivedReviews = false;
var review = {
// some data
};
$scope.reviews = addReviews.getReviews().query(
function(response) {
$scope.reviews = response;
$scope.receivedReviews = true;
},
function(response) {
$scope.reviews = response;
// print error message
}
);
console.log($scope.reviews); // showing empty array
};
}]);
In routes.js, I have configured my route as:
var Reviews = require('./models/reviews');
...
app.post('/reviews', function(req, res) {
Reviews.create(req.body, function(err, post) {
if (err) {
return res.send(err);
}
return res.json(post);
});
});
I am trying to post a new review to the Reviews collection. However, $scope.reviews is showing an empty array. I logged the requests, and it shows a GET request is being to /reviews instead of POST. I think I should use save() instead of query(), but I have seen some tutorials online where they used query() despite the method being PUT/POST in the service. I am really confused. Can anyone point out how I can post the data (in var review) to the Reviews collection?
There are some issues with your code on the angular side of things.
You want to use $resource as an all-purpose object to communicate with the API. It has built-in functionality to:
query: get all resources from a given API endpoint
get: a single resource, usually by specifying that resource's id
save: post, with an object sent across in the body of the request. NOTE: you don't need the {'save': {method: 'POST'}} in your $resource configuration, you get it for free.
remove and delete: self-explanatory
So you'd want to set up your reviews factory (incl. url constant) like:
angular.module('myApp', ['ngResource'])
.constant('baseURL', 'http://localhost:8080/')
.factory('Reviews', ['$resource', 'baseURL', function($resource, baseURL) {
return $resource(baseURL+'reviews/:id', {id: '#id'});
}]);
If you want to have access to all saved reviews in your controller, as $scope.reviews, you'd do something like:
angular.module('myApp')
.controller('reviewController', ['$scope', 'Reviews', function($scope, Reviews) {
// hit API endpoint to get all reviews
// will have to have app.get('/reviews', function(req, res) {...})
// configured in your node code
Reviews.query(function(data) {
$scope.reviews = data;
}, function(error) {
console.log(error);
});
// and if you want to take a user-written review, say $scope.userReview,
// from the view and save it to the database on click function submitReview()...
$scope.userReview = {
message: '',
createdTime: null
};
// ^ not sure what your ReviewSchema looks like on the backend, but for example...
$scope.submitReview = function() {
if ($scope.userReview.message.length) {
$scope.userReview.createdTime = Date.now();
Reviews.save($scope.userReview);
// ^ this will make POST request with the $scope.userReview object as the request body
}
};
}]);
The create method on your back end looks fine. The object (or maybe just string) you send across will have to match your review schema. You may want to log the request body to make sure you're getting what you expect.
Have a look at this short post on using $resource to interact with RESTful APIs, and (the slightly more confusing) angular $resource docs, for more information on the $resource service.
Hope this helps you!

Ionic/Angular js Parsing JSON data from server

How to parse JSON object from server using Ionic/Angular js? This is work for me when loading json from /js folder:
var rssApp = angular.module('myApp', []);
rssApp.controller('datas', ['$scope', '$http', function($scope,$http) {
$http.get("js/data.json") // <=== this
.then(function (response)
{
$scope.dat = response;
});
}]);
but when i load json from webserver,i got blank, this is my code :
var rssApp = angular.module('myApp', []);
rssApp.controller('datas', ['$scope', '$http', function($scope,$http) {
$http.get("http://localhost/data.json") //<== this
.then(function (response)
{
$scope.dat = response;
});
}]);
Thanks for your help..
Analyzing what you have done so far, i suppose your data is being returned as an array from the webserver since you are getting blank with your code. So, you should assign the response[0] to $scope.dat.
var rssApp = angular.module('myApp', []);
rssApp.controller('datas', ['$scope', '$http', function($scope,$http) {
$http.get("http://localhost/data.json") //<== this
.then(function (response)
{
$scope.dat = response[0];
});
}]);
First
Angular's $http promise response contains a few properties.
The data returned from the server would be in the data property.
From the Angular docs:
The response object has these properties:
data – {string|Object} – The response body transformed with the
`transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Also you want to make sure that the endpoint is pointing at the correct resource.
I.e if data.json is inside your application file, then the path would be path/to/data.json. This should be easy to identify, because you'll get a 404 status code with your response object.
Solution
So you might want to do something like:
var endpoint = "path/to/data.json";
$http.get(endpoint).then(function (response) {
$scope.dat = response.data;
});
One more thing
Also, if in doubt user console.debug(response); which will allow you to inspect the response object.

Resources