var app = angular.module('app');
// register the interceptor as a service
app.factory('myHttpInterceptor', function($q ) {
return {
'request': function(config) {
return config;
}
};
});
I am trying to modify the urls of api calls and append the api url to the start of the ajax calls in the interceptor insted of each service function like
function getAssesmentResults(params) {
return $http.get(url.api + '/results', {params: params})
.then(function(response) {
return response.data;
});
}
However the interceptor intercepts all http requests like .css or .html or .json files. What is a good way to modify the urls in the interceptor without modifying other http requests?
$http has a facility to intercept and rewrite URLs that is configured on the $httpProvider. When I run in production, I have an extra token: '/rest/' compared with development mode and I detect production mode ( prefix packing ) in the interceptor. This is in my app.js
var rest_srvr = 'http://dev-pc.example.com:8000'
app.factory('REST_Interceptor',[
'$location',
function($location) {
var request = function(config) {
if (RegExp('packing','i').test(window.location.host)) {
return config
}
var rest_request_regex = new RegExp('^.*?/rest/(.*)$')
//console.log('config.url=%s',config.url)
config.url = config.url.replace(rest_request_regex,rest_srvr+'/$1')
var files_request_regex = new RegExp('^/(files/(.*))$')
config.url = config.url.replace(files_request_regex,rest_srvr+'/$1')
//console.log(' is now config.url=%s',config.url)
return config
}
var translate_subpath = function(subpath) {
return request({url:'https://'+$location.host()+subpath}).url
}
return {
request: request,
translate_subpath: translate_subpath
}
}])
app.config([
'$httpProvider','$cookiesProvider',
function($httpProvider, $cookiesProvider) {
if (!RegExp('packing','i').test(window.location.host)) {
$httpProvider.interceptors.push('REST_Interceptor')
}
}])
I would create a service that wraps the $http. Then in your code you'll always call this wrap instead of $http and will be able to do whatever you want with the request before it is sent. Just a simple example:
module.factory('myHttp', function($http){
return {
get: function(url, params){
var newUrl = "base-api-url/" + url;
return $http.get(newUrl, params);
}
}
})
Use the generic service for this:
Generic service
appCless.factory("$comum", function($http, $q, $injector) {
function ajax(url, parametros, metodo) {
var requisicao = $http({
method: metodo,
url: url,
data:parametros
});
var promessa = requisicao.then(
function(resposta) {
return(resposta.data);
},
function(resposta) {
return($q.reject("Something went wrong"));
}
);
return promessa;
}
return({
ajax:ajax
});
});
Service
app.factory("$categoriaproduto", function($comum) {
var categoria;
return {
buscar : function(neoId) {
var promessa = $comum.ajax("/fusion/services/roi/category/product/search", "", "POST");
promessa.then(function(req) {
categoria = req.data;
});
return promessa;
},
cache : function() {
return categoria;
}
};
});
Related
I have the following function (credit) that wraps an AngularJS $http function in a way that it invokes browser XHR when running on desktop, but invokes cordova-plugin-advanced-http if on mobile.
It seems that this works when I use $http({method:'get/post'}...) but doesn't work if I call the convenience shortcuts like $http.get(...)
Can someone suggest what modification I need to make?
$provide.decorator('$http', ['$delegate', '$q', function($delegate, $q) {
// create function which overrides $http function
var $http = $delegate;
var wrapper = function () {
var url = arguments[0].url;
var method = arguments[0].method;
var isOutgoingRequest = /^(http|https):\/\//.test(url);
if (window.cordova && isOutgoingRequest) {
console.log ("**** -->"+method+"<-- using native HTTP with:"+url);
var d = $q.defer();
var options = {
method: method,
data: arguments[0].data,
headers: arguments[0].headers,
timeout: arguments[0].timeout
};
cordova.plugin.http.sendRequest(url,options,
function (succ) {
console.log ("*** Inside native HTTP success with:"+JSON.stringify(succ));
try {
if (options.headers && options.headers['x-parse']=='text')
d.resolve({"data":succ.data});
else
d.resolve({"data":JSON.parse(succ.data)});
return d.promise;
}
catch (e) {
d.resolve({"data":succ.data});
return d.promise;
}
},
function (err) {
console.log ("*** Inside native HTTP error");
d.reject(err);
return d.promise;
});
return d.promise;
}
else {
console.log ("**** "+method+" using XHR HTTP for "+url);
return $http.apply($http, arguments);
}
};
Object.keys($http).filter(function (key) {
return (typeof $http[key] === 'function');
}).forEach(function (key) {
wrapper[key] = function () {
// Apply global changes to arguments, or perform other
// nefarious acts.
// console.log ("KEY="+key);
return $http[key].apply($http, arguments);
};
});
return wrapper;
}]);
If I understood your intent correctly, the way you're assigning the HTTP methods that hang off wrapper won't invoke the contents of your wrapper function.
Note that the parameters of the $http convenience functions vary.
Examples:
GET is described as: get(url, [config])
POST is described as: post(url, data, [config])
With the above in mind, here's one way of delegating back to your wrapper function that switches between XHR and the Cordova plugin when the $http convenience methods are used:
wrapper[key] = function () {
var url = arguments[0];
if (['get', 'delete', 'head', 'jsonp'].indexOf(key) !== -1) {
// arguments[1] == config
return wrapper(Object.assign({
method: key,
url: url,
}, arguments[1]));
} else {
// POST, PUT, PATCH
// arguments[1] == data
// arguments[2] == config
return wrapper(Object.assign({
data: arguments[1],
method: key,
url: url,
}, arguments[2]));
}
};
Here is a working solution I eventually arrived at.
// Wraps around $http that switches between browser XHR
// or cordova-advanced-http based on if cordova is available
// credits:
// a) https://www.exratione.com/2013/08/angularjs-wrapping-http-for-fun-and-profit/
// b) https://gist.github.com/adamreisnz/354364e2a58786e2be71
$provide.decorator('$http', ['$delegate', '$q', function($delegate, $q) {
// create function which overrides $http function
var $http = $delegate;
var wrapper = function () {
var url;
var method;
url = arguments[0].url;
method = arguments[0].method;
var isOutgoingRequest = /^(http|https):\/\//.test(url);
if (window.cordova && isOutgoingRequest) {
console.log ("**** -->"+method+"<-- using native HTTP with:"+encodeURI(url));
var d = $q.defer();
var options = {
method: method,
data: arguments[0].data,
headers: arguments[0].headers,
timeout: arguments[0].timeout,
responseType: arguments[0].responseType
};
cordova.plugin.http.sendRequest(encodeURI(url),options,
function (succ) {
// automatic JSON parse if no responseType: text
// fall back to text if JSON parse fails too
if (options.responseType =='text') {
// don't parse into JSON
d.resolve({"data":succ.data});
return d.promise;
}
else {
try {
d.resolve({"data":JSON.parse(succ.data)});
return d.promise;
}
catch (e) {
console.log ("*** Native HTTP response: JSON parsing failed for "+url+", returning text");
d.resolve({"data":succ.data});
return d.promise;
}
}
},
function (err) {
console.log ("*** Inside native HTTP error: "+JSON.stringify(err));
d.reject(err);
return d.promise;
});
return d.promise;
}
else { // not cordova, so lets go back to default http
console.log ("**** "+method+" using XHR HTTP for "+url);
return $http.apply($http, arguments);
}
};
// wrap around all HTTP methods
Object.keys($http).filter(function (key) {
return (typeof $http[key] === 'function');
}).forEach(function (key) {
wrapper[key] = function () {
return $http[key].apply($http, arguments);
};
});
// wrap convenience functions
$delegate.get = function (url,config) {
return wrapper(angular.extend(config || {}, {
method: 'get',
url: url
}));
};
$delegate.post = function (url,data,config) {
return wrapper(angular.extend(config || {}, {
method: 'post',
url: url,
data:data
}));
};
$delegate.delete = function (url,config) {
return wrapper(angular.extend(config || {}, {
method: 'delete',
url: url
}));
};
return wrapper;
}]);
is there any possibility to detect the completion of HTTP request in angular1 ?
product factory :
app
.factory('productFactory', ['$http','config',
function($http,config) {
var url = config.domainBase +':'+config.domainPort +config.additionalPath+'/Product/All'
return {
getAll: function() {
return $http.get(url);
}
};
}
]);
Product Controller :
var req = productFactory.getAllServers();
req.success(function(response) {
//....
}).
error(function(error){
//error
});
Take a look at $q injector
var deferred = $q.defer();
var params = {
...
};
$http.post('http://www.example.com', JSON.stringify(params))
.success(function(object) {
// On success
})
.error(function(object, status) {
// On error
});
return deferred.promise;
Using AngularJS for my application and for http post the server needs a token that we can get by http get. But I want to run the token_generate() function before each http call, because sometimes the token expires
token = function() {
var api = AuthService.getToken();
api.success(function (response) {
var token = response.token;
$http.defaults.headers.common['X-CSRF-TOKEN'] = token;
});
};
token();
You need to register an $http interceptor:
(function(window, angular) {
function tokenizerConfig($httpProvider) {
function registerInterceptors($q, $http, AuthenticationService) {
var interceptors = {};
interceptors.request = function(configs) {
if(AuthenticationService.isTokenValid) {
return $q.when(configs);
}
var qs = {};
return $http
.get(TOKEN_API, { cache: false, params: qs})
.then(function(result) {
AuthenticationService.setToken(result.data.token);
return configs;
})
;
};
return interceptors;
}
$httpProvider.interceptors.push(['$q', '$http', 'AuthenticationService', registerInterceptors]);
}
angular
.module('tokenizer', [])
.config(['$httpProvider', tokenizerConfig])
})(window, window.angular);
So i can get data from a URL if i do it from with in my controller. But if i take that and move it into a factory it doesn't work. So what am i doing wrong?
angular.module('starter.notifications', [])
.factory('Notifications', function($http) {
var link = "http://localhost:8000/notifications";
var notifications = [];
return {
getAll: function()
{
return $http.get(link).success(function(data, status, headers, config) {
notifications = data;
return notifications;
});
},
This code works if i move it into a controller, but why doesn't it work in a factory?
This is how i did it.
In the top of your app.js
angular.module('app', ['ionic', 'app.controllers', 'app.services','ngCordova'])
Let ionic knows you have an services.js by declaring it.
services.js (an http post request example)
angular.module('app.services', ['ngCordova'])
.factory('dataFactory', function($http, $cordovaGeolocation){
var dataFactory = {};
dataFactory.login = function(username, password){
var config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}
var data = 'userID=' + username + '&password=' + password +'';
var httpAddressDoLogin = "http://YOURURL";
return $http.post(httpAddressDoLogin, data, config);
};
return dataFactory;
})
In your controller:
dataFactory.login(username, password).then(function(resp) {
Hope that helps.
On services.js $http.get resulting promise not object array. To make it work write like this on your services.js
angular.module('starter.services', [])
.factory('Actor', function($http) {
var actors = $http.get('http://ringkes/slim/snippets/actor').then(function(resp) {
if (resp) {
return = resp['data'];// This will produce promise, not array so can't call directly
} else {
console.error('ERR', err);
}
});
return {
all: function() {
return actors;
}
};
});
then call it on controller like this:
controller('DashCtrl', function($scope,Actor,$http) {
Actor.all().then(function(actors){ $scope.actors = Actor.all();
});
});
var app = angular.module('app', ['ngResource']);
app.factory('UserFactory', function ($resource) {
return $resource('/com/vsoft/rest/users', {}, {
query: {
method: 'GET',
params: {},
isArray: false
}
});
});
app.controller('MyCtrl1', ['$scope', 'UserFactory', function ($scope, UserFactory) {
UserFactory.get({}, function (userFactory) {
$scope.firstname = userFactory.firstName;
$scope.lastname = userFactory.lastName;
});
});
}]);
i added above app in my html.But the app and angular-resource.js but my app.js is not exeuting.
If i removed ngResource module and $resource alert is coming.But if i used ngResource im nt getting alert.
Please help in this.If any one knows any Good Example to use Restful services with angularjs .Please Kindly send Url or code.
Please help me.
i called{{firstname}}
in my html but its not coming .
I use a service for handling RESTful messages
app.service('restService', function ($http, $log) {
'use strict';
var self = this;
var BASE_URL = "base/url/";
//First way how to do it
self.httpGet = function (url) {
$log.info("HTTP Get", url);
return postProcess($http({method: 'GET', url: BASE_URL + url}));
};
//Second way how to do it
self.httpPut = function (url, object) {
$log.info("HTTP Put", url);
return postProcess($http.put(BASE_URL + url, object));
};
self.httpPost = function (url, object) {
$log.info("HTTP Post", url);
return postProcess($http.post(BASE_URL + url, object));
};
self.httpDelete = function (url) {
$log.info("HTTP Delete", url);
return postProcess($http.delete(BASE_URL + url));
};
function postProcess(httpPromise) {
return httpPromise.then(function (response) {
if (response.status === 200) {
return response;
}
//Other than 200 is not ok (this is application specific)
failure(response);
}, function (response) {
failure(response);
});
}
/**
* Promise for failure HTTP codes
* #param response the HTTP response
*/
function failure(response) {
//Error handling
}
});
usable as
restService.httpGet("categories").then(function (response) {
categoryData = angular.fromJson(response.data);
//Broadcast an event to tell that the data is ready to be used
$rootScope.$broadcast("categoriesReady");
});