Store domain in one place in angular js service - angularjs

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};
});

Related

"Subclass" http and httProvider in AngularJS

I want to make a separate $http module that does exactly the same thing as the original $http module, but appends a baseURL to every request.
I know that this can be done with an interceptor, but I don't want this behavior for every instantiation of $http, only for my "subclass" (not really possible in JS) called something like $httpAPI or something.
I've seen similar solutions that do a lot of work by hand. Can I just clone $http and put an interceptor on the cloned version?
Create a service that has $http and an injectable parameter. Implemented the common function you use (get, post, put,... etc). In this new service the baseUrl can be either injected or hard coded.
function myHttp($http, baseUrl){
var internalBaseUrl = baseUrl || 'http://www.baseUrl.com/';
return {
get: function(url){
return $http.get(baseUrl + url);
},
post: function(url, data){
return $http.get(baseUrl + url, data);
}
}
}

AngularJS $resource Headers POST

I would like to know how to pass headers to AngularJS $resource method
Here is the factory method
.factory('DataRepository', function ($resource) {
return $resource(serviceUrlPrefix + '/api/v1/AppList/:id', { id: '#id' }, { 'query': { method: 'GET', isArray: false }, 'update': { method: 'PUT', AppList: '#req', headers: { 'X-Requested-With': 'XmlHttpRequest' } } });
});
Here is the call to the dataRepository
dataRepository.update({ id: req[uniqueIDColumn] }, req, function (data) {
},
function (error) {
});
This code works fine. But i have few queries
Question 1:
Rather than specifying the headers in the factory method , how can i specify it in the call to the factory method? I tried few methods but it didnt work out.
Question 2:
I specified the header in the update method in the factory. When i perform "Save" using that factory, that header has been taken by default. But i have specified it explicitly for PUT method. Right? Why and how?
Question 3:
If i would like to specify the header for the particular factory in common for all Http methods, what is the way to do it?
Question 4:
What is the nomenclature for passing the parameters and the significance of "#" symbol before parameter and also in the below part, AppList is the parameter name used in the WebAPI, is it mandatory that it should match the parameter name in the WebAPI method, if its not matching, its not working:(
AppList: '#req'
I'm afraid we don't use $resource, but it does depend on $http. We configure the header with the below. Not sure about the rest of your questions.
I will say that we also do not use $http directly. We created our own "requestHelper" service that we inject everywhere. That allows us to inject things before making calls to $http as well as catch the response before passing the result on to the real caller. Helps with common error handling.
Configure headers for $http:
module.config(['$httpProvider', function ($httpProvider) {
$httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
}]);

AngularJS : How to inject a service into a factory

I have a REST backend which provides a hashmap of API methods. This allows the front end to use a keyname to map to the API method instead of needing to know the entire REST url.
Ex:
{
CHARGE.GET_CHARGE_INFO: /provider/charge/getChargeInfo/{{providerId}}/{{chargeId}}
CHARGE.LIST_CHARGES: /provider/charge/listCharges/{{providerId}}
CHARGE.LIST_TYPES: /provider/charge/listTypes
}
There is a service which is responsible for loading the hashmap from the REST API.
app.service('preloader', function ($http, globals, $interpolate, $q) {
var self = this;
var endPointsList = $http.get(globals.apiPath + globals.endPointsPath, {}).success(function (data) {
self.endPoints = data;
});
return {
endPointsList: endPointsList,
getResourceEndPoint: function( endPoint ){
if (!self.endPoints[endPoint]) {
// To avoid misleading errors
throw ("Endpoint not found. \r\nEndpoint: " + endPoint + "\r\nFound: " + self.endPoints[endPoint]);
}
// reformat
return globals.apiPath + self.endPoints[endPoint].replace(/{{([^}]+)}}/g, ":$1");
}
};
I'm trying to write a $resource which uses this service, but the problem is when the service is injected into the factory, it has not yet been initialized and consequently calls to the method to retrieve the endpoint throw errors.
app.factory('providerFactory', ['$resource', 'preloader',
function ($resource, preloader) {
return $resource( "", null,
{
"getTypes" : {
method: 'GET',
url: preloader.getResourceEndPoint('PROVIDER.LIST_TYPES')
},
"get": {
method: 'GET',
url: preloader.getResourceEndPoint('PROVIDER.GET_PROVIDER_INFO'),
params: {
providerId: '#providerId'
}
}
}
);
});
Error Msg:
TypeError: Cannot read property 'PROVIDER.LIST_TYPES' of undefined
at Object.getResourceEndPoint (http://localhost:8888/client.git/build/app.min.js:3:8967)
If I step through the code, I see that the factory's preloader.getResourceEndPoint() calls are calling the service before the service has completed its initialization of the endPointsList.
What can I do to avoid this problem? Do I have to use a $q promise? It seems like overkill for something like this. If so then I have to wonder if this is even the right approach to get something like this to work, but I'm not sure what approach to use.
I'm still learning AngularJS so I'm not entirely sure of the correct way to proceed. Ive inherited this code so if it seems that it is convoluted/complicated for nothing, I'd appreciate insights on how to improve it.

Configuring external http service in 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;
});
});

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.

Resources