As per the bellow code, Axios request interceptors can be used to so something, before the request is sent or when there is an error in the request. Like wise, Is there a way to identify the request completion event as well with axios request interceptors (Not with response interceptors)?
axios.interceptors.request.use(function (config) {
// Do something before request is sent
return config;
}, function (error) {
// Do something with request error
return Promise.reject(error);
});
Thanks,
Try with the request handler
const requestHandler = (request) => {
if (isHandlerEnabled(request)) {
//your code here
})
}
return request
}
// Add interceptors
axiosInstance.interceptors.request.use(
request => requestHandler(request)
)
Reference link:- https://codepen.io/teroauralinna/pen/vPvKWe?editors=0010
Related
My app uses IBM Watson Speech-to-Text, which requires an access token. From the command line I can get the access token with curl:
curl -X GET --user my-user-account:password \
--output token \
"https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api"
When I make an HTTP request using Angular's $http service I get a CORS error:
var data = {
user: 'my-user-account:password',
output: 'token'
};
$http({
method: 'GET',
url: 'https://stream.watsonplatform.net/authorization/api/v1/token?url=https://stream.watsonplatform.net/speech-to-text/api',
data: data,
}).then(function successCallback(response) {
console.log("HTTP GET successful");
}, function errorCallback(response) {
console.log("HTTP GET failed");
});
The error message says:
No 'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://127.0.0.1:8080' is therefore not allowed
access. The response had HTTP status code 401.
As I understand, it's not possible to do CORS from Angular; CORS has to be done from the server. I know how to do CORS with Node but I'm using Firebase as the server.
Firebase has documentation about making HTTP requests with CORS. The documentation says to write this:
$scope.getIBMToken = functions.https.onRequest((req, res) => {
cors(req, res, () => {
});
});
First, that doesn't work. The error message is functions is not defined. Apparently functions isn't in the Firebase library? I call Firebase from index.html:
<script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>
My controller injects dependencies for $firebaseArray, $firebaseAuth, and $firebaseStorage. Do I need to inject a dependency for $firebaseHttp or something like that?
Second, how do I specify the method ('GET'), the URL, and the data (my account and password)?
if you want to send credentials with angular, just set withCredentials=true. I am also using CORS with Angular v4, for your HTTP header error, you are right. Header Access-Control-Allow-Origin must be added on server side, check if you have settings in your api to allow certain domains, urls, pages, because google api's has this function, so check where you get token there should be some settings.
Here is example, how I am calling API with CORS, using typescript:
broadcastPresense(clientId: string) {
const headers = new Headers({'Content-Type':'application/json','withCredentials':'true'});
return this.http.post('http://localhost/api.php',
{
'jsonrpc': '2.0',
'method': 'somemethod',
'params': {'client_id': clientId},
'id': CommonClass.generateRandomString(16)
},{headers: headers, withCredentials:true}).map(
(res: Response) => {
console.log(res);
const data = res.json();
console.log(data);
if (data.error == null) {
return data.result;
} else if (data.error != null) {
throw data.error;
}
throw data.error;
}
).catch(
(error) => {
this.router.navigate(['/error',3],{queryParams: {desc:'Server error'}});
return Observable.throw(error);
}
);
}
Hope it helps :)
The answer is to use Cloud Functions for Firebase, which enable running Node functions from the server. Then you use the Node module request to send the HTTP request from Node.
I want to return cached response before timeout happened and then renew cache.
I tried this:
.factory('TestInterceptor', TestInterceptor);
function TestInterceptor($q) {
return {
request: request,
response: response
};
function request(config) {
...
return $q.resolve(fakeResponse);
...
}
function response() {
....
}
}
but it doesn't work.
It is not possible. As the manual says,
request: interceptors get called with a http config object. The function is free to modify the config object or create a new one. The function needs to return the config object directly, or a promise containing the config or a new config object.
Suppose I registered several HTTP interceptors in angular.js app:
$httpProvider.interceptors.push(function() {
return {
request: function(config) {
console.log("interceptor A request");
return config;
},
response: function(res) {
console.log("interceptor A response");
return res;
}
};
});
$httpProvider.interceptors.push(...); // interceptor B with similar code
$httpProvider.interceptors.push(...); // interceptor C with similar code
In which order will they be executed?
It seems that the interceptors are executed:
in registration order for requests
in reverse registration order for responses
Log:
interceptor A request
interceptor B request
interceptor C request
(request happens here)
interceptor C response
interceptor B response
interceptor A response
I am using the following to show a loading screen whenever I am performing a http request however sometimes if there is an error then it will stay loading (because of the backdrop the app becomes unusable). Rather than hide it on every error checker I was wondering if it is possible to call the timeout after 5 seconds?
.config(function($httpProvider) {
$httpProvider.defaults.timeout = 5000;
$httpProvider.interceptors.push(function($rootScope) {
return {
request: function(config) {
$rootScope.$broadcast('loading:show')
return config
},
response: function(response) {
$rootScope.$broadcast('loading:hide')
return response
}
}
})
})
Following Jess's answer it now looks like this :
.config(function($httpProvider) {
$httpProvider.defaults.timeout = 5000;
$httpProvider.interceptors.push(function($rootScope) {
return {
request: function(config) {
$rootScope.$broadcast('loading:show')
return config
},
response: function(response) {
$rootScope.$broadcast('loading:hide')
return response
},
responseError: function(response) {
$rootScope.$broadcast('loading:hide')
return response
},
requestError: function(response) {
$rootScope.$broadcast('loading:hide')
return response
}
}
})
})
However I cannot seem to be able to put an alert in the requestError to inform the user.
Question
How can I implement an alert to notify the user of the error that has occurred?
try adding responseError and requestError so like this:
responseError: function(responseError) {
$rootScope.$broadcast('loading:hide')
return responseError
and do this again with requestError,
This is from the angular http interceptors docs
requestError: interceptor gets called when a previous interceptor threw an error or resolved with a rejection.
responseError: interceptor gets called when a previous interceptor threw an error or resolved with a rejection.
Edit to answer comment:
so if you want to throw a alert on responseError than a add a $rootScope.$broadcast('response:error')
in the responseError function
then in the controller you want to throw the alert in just do a
$scope.$on('response:error', function(){throw the error here});
you can also do the same for requestError
this works because $broadcast -- dispatches the event downwards to all child scopes
I have created http interceptors and attached to my main app as below:
angular.module('app',['ui.router'])
.factory('AuthInterceptor',function($window,$q){
return{
request: function(config){
console.log("config object is");
console.log(config);
if($window.sessionStorage.getItem('token')){
config.headers['x-access-token']= $window.sessionStorage.getItem('token');
}
return config || $q.when(config);
},
response: function(response){
console.log("response object is:");
console.log(response);
if (response['status'] >= 400) {
console.log("Not Authorized.kindly login first");
$state.transitionTo('login');
}
return response || $q.when(response);
}
};
})
.config(function($httpProvider){
$httpProvider.interceptors.push('AuthInterceptor');
});
On the server-side (some express code) I am checking if the user is authorized or not and if not I respond with the following code (only displaying a subset of code to keep things concise):
if(!req.user){
res.send('Not authorized',400);
}
The server code works fine (i can see it in the network tab of the chrome developer tools)
However AuthInterceptor.response() does nto get called.
However do note that the AuthInterceptor.response() does get executed when the response status is 200
So I am confused.. why is it not intercepting 400 statuses ?
If the response status code is outside of the range [200-299], then the responseError interceptor is called.
You need to provide a responseError interceptor:
return {
request: function (config) {...},
responseError: function (rejection) {...}
};