Configuring external http service in angularjs - angularjs

I have a single page angular app which calls a RESTish service. How can I configure the base URL for my REST server so that in my services I can use relative URLs? Also, as I was playing around with the following interceptor I got an error where angular-ui router seemed to be using http to get views so this was affected by the middleware. Basically I guess I want a second http service to inject into my services that has this middleware, how can I do this?
app.config(["$httpProvider", function($httpProvider) {
$httpProvider.interceptors.push('middleware');
}]);
app.factory('middleware', function() {
return {
request: function(config) {
// need more controlling when there is more than 1 domain involved
config.url = "http://localhost:8080" + config.url;
return config;
}
};
});

The $http services is very important (and widely used) inside Angular.
You shouldn't alter it like this.
For handling requests to an API, it is best to create a dedicated service (even if it's a wrapper around $http).
E.g.:
.service('API', function ($http) {
var baseUrl = 'http://localhost:8080/';
this.get = function (path, config) {
return $http.get(baseUrl + path, config);
}
...
});
Then you can use your service for all API calls:
.controller('someCtrl', function (API) {
API.get('items').success(function (data) {
$scope.items = data;
});
});

Related

Angularjs + interceptors + add query parameters for only http request( not html,js,css files)

I am using angularjs, In backend I check every api authenticated.
Every request should be checked the parameter access_token.
$provide.factory('MyHttpInterceptor', function($q, $location, $localStorage) {
return {
request : function(config) {
config.params = config.params || {};
if ($localStorage.access_token) {
config.params.access_token = $localStorage.access_token;
}
return config || $q.when(config);
},
};
});
// Add the interceptor to the $httpProvider.
$httpProvider.interceptors.push('MyHttpInterceptor');
I using this code. Its working good, but I saw in development tools(Network) the html, css, js files also added the parameters.
like.
http://localhost/webapp/views/template/left-menu.html?access_token=xxxxxxxxxxxxxxxxx
http://localhost/webapp/css/index.css?access_token=xxxxxxxxxxxxxxxxx
But I don't like to send access_token to all http request(html,css,js).
I like to send the access_token for what are have prefix api
http://localhost:9090/api/user/get?access_token=xxxxxxxxxxxxxxxxxxxxxx
//I think the solution is find the http url and grep the text api, if found means add the parameter. Don't konw this is good approach.
Please me the good approach.
I expect only backend api request only.
Also I don't expect every serive http request to add parameter.
Its possible to add common one place in config ?
You can check url:
$provide.factory('MyHttpInterceptor', function($q, $location, $localStorage) {
return {
request : function(config) {
var apiPattern = /\/api\//;
config.params = config.params || {};
if ($localStorage.access_token && apiPattern.test(config.url)) {
config.params.access_token = $localStorage.access_token;
}
return config || $q.when(config);
}
};
});
// Add the interceptor to the $httpProvider.
$httpProvider.interceptors.push('MyHttpInterceptor');

Store domain in one place in angular js service

I have the following example method in angular service:
function send(data) {
return $http({
method: 'POST',
url: 'https://test.domain/test/send',
data: $httpParamSerializerJQLike(data)
});
}
The domain that is https://test.domain/test is the same for all the services in my app. I do not want to write it every time in every services. I can abstract it in a constant and inject it in every service but I wonder if there is more clever solution. Is it possible to store the domain part in an interceptor or any other suggestions are welcome. Please provide code examples as I am quite new to angular. Thanks
I'd say rather than abstracting the values out into a constant, you should abstract the $http call into a service. Then you can just inject that service into all of your other services in place of $http. For example:
angular.module('myApp').factory("myHttp", ["$http", function ($http) {
return function (config) {
config.url = "https://test.domain/test" + config.url;
return $http(config);
};
}]);
So effectively what this service is doing is proxying calls to $http, but prepending your common URL to the beginning - this would allow you to change your example code to:
function send(data) {
return myHttp({
method: 'POST',
url: '/send',
data: $httpParamSerializerJQLike(data)
});
}
Of course, this is just one example of how you could do an abstraction like this - the myHttp service could take any form you like, depending on what would be most convenient for you. I think this is a better solution than using an interceptor in this case, as it allows you to pick and choose when you use it, rather than it being applied to every single HTTP request.
create an interceptor and on requests change the url.
angular.module('app').factory('domainInterceptorService', [
function () {
var request = function (config) {
config.url = 'https://test.domain/' + config.url;
}
return config;
}
return {request: request};
});

Angular JS global config for resource success query

I have implemented resources in my single page angular app which fires to my REST client server. I have made different services for each resource. Now my REST server is sending a value in response header, now I want to know a proper way where I can retrieve that value from headers.
My service code:
app.service('$job', function($resource) {
var job = $resource(service_base_url+'jobs.json/:id');
return job;
});
My controller which is getting headers:
app.controllerProvider.register('JobPostsController',['$scope','$job', function($scope, $job) {
$scope.jobs = {};
$scope.job_titles = {};
$job.query(function(jobs,responseHeaders){
var headers = responseHeaders();
some_function(headers.user);
$scope.jobs = jobs.jobs;
});
}
]);
I am getting headers in my above code, but I don't want to inject it in all controllers. So is there a proper way to do it? Some single config code which will run for all future resources request or some kind of event which can be only triggered when successful resource response with 200 OK
Try interceptor.
I don't know exactly your logic. You could register a global interceptor which intercepts all requests:
angular.module('App', [])
.config(function ($httpProvider){
$httpProvider.interceptors.push(function() {
return {
'response': function(response) {
var headers = response.headers();
some_function(headers.user);
return response;
}
};
});
});
or just register an interceptor which runs only for all requests of this query.
app.service('$job', function($resource) {
var job = $resource(service_base_url+'jobs.json/:id',{}, {
'query': {
method:'GET',
isArray:true,
interceptor: {
'response': function(response) {
var headers = response.headers();
some_function(headers.user);
return response;
}
}
}
});
return job;
});
Side notes:
Should not use $ prefix for your service name as it's reserved for angular, it may conflict with angular future versions.
I guess you need .factory instead of .service
You can set up the service in a run block like:
angular.module('myApp', [])
.run(['$rootScope', '$job',function ($rootScope, $job) {
$rootScope.jobs = {};
$rootScope.job_titles = {};
$job.query(function(jobs,responseHeaders){
var headers = responseHeaders();
some_function(headers.user);
$rootScope.jobs = jobs.jobs;
});
}]);
The only drawback your service is global to the app
I would go with a base service factory. This would allow you to have common service related functionality in one place
app.factory('ServiceBase', function () {
function ServiceBase() {
this.responseHeaders = function responseHeaders(resp){
// todo
};
}
return ServiceBase;
});
app.service('$job', function($resource, ServiceBase) {
var service = function () {
// $job related functions here
};
angular.extend(service, new ServiceBase());
return service;
});
Now anything in the ServiceBase is accessible to the controller and to the service. This allows you to have common functionality, has no new injection dependencies (on the controller), and is easy to extend further.
I think angulrjs response interceptors can help u for this.

AngularJS remote client Properties share to controllers/services

I want to develop an AngularJS web client for which the REST backend may be located on a different server.
So basically I am thinking of having a property input field on the frontend where for each session I will enter the base REST url (e.g., http://localhost:8080/backend/rest/)
Is there some sort of best practice to be able to share the base url amongst all controller/factories/services in order to include it for all $http requests?
I would configure an HTTP request interceptor service that would simply prepend the value to the URL passed to the $http service. Something like the following (not tested):
// register the interceptor as a service
$provide.factory('pathPrependerInterceptor', function() {
var _path = 'http://localhost:8080/backend/rest'; // default value
return {
request: function(config) {
config.url = _path + config.url
return config;
},
setPath: function(path) {
_path = path;
}
}
});
$httpProvider.interceptors.push('pathPrependerInterceptor');
I think the bast way would be to acomplish this with the use of interceptors. You can read more about this topic in the AngularJs documentation.
The idea is to set up an interceptor that will preappend the base url to each request something like this:
var app = angular.module('MyApp',[]);
app.config(['$httpProvider', function($httpProvider) {
$httpProvider.interceptors.push(function($q) {
return {
'request': function(config) {
config.url = "http://api.openweathermap.org/data/2.5/" + config.url
return config;
}
};
});
}]);
I hope you got an idea.
There is JSFiddle that incorporates this idea.
The other answers are from a more experienced bunch, so take this with a pinch of salt, but they seem like overkill to me. You're configuring an application-wide variable which needs injection. Using
module.value("baseRestUrl", ...)
lets you inject baseRestUrl wherever it's required.

Is it possible AngularJS acess request and session scope of my application?

When I make a request and set on the request and session scope (server side) some attributes. I would like to know if is it possible to get with AngularJS these attributes at my server side.
If you are looking for any "session integration" for authentication purposes, take a look at Spring Session in conjunction with Spring Security. I wrote a little sample application that illustrates how to integrate AngularJS with Spring Security by exposing the session id as an HTTP header (x-auth-token). The corresponding blog post is here.
Yes it is possible, typically one can do as charlietfl said very easily when performing an asynchronous login. Just return some JSON containing upon a successful login.
I store the returned JSON in a ".value" service:
var app = angular.module('app', [])
.value('appData', {})
.factory('authService', ['$http', '$q', 'appData',
function authService($http, $q, appData) {
var setAppData = function(data) {
angular.copy(data, appData);
};
return {
login: function() {
var deferred = $q.defer();
$http.post('/auth', data)
.success(function(response){
deferred.resolve(response);
setAppData(response);
})
.error(function(reason){
deferred.reject(reason);
});
return deferred.promise;
},
logout: function() {
//...http call to logout
setAppData({});
}
};
}
])
;

Resources