Laravel-Debugbar not catching AJAX call (Angular call) - angularjs

I am working on project which front end is AngularJS & Backend is Laravel4.
And I am using barryvdh's laravel-debugbar package as debugger
My problem is debugbar showing data when first time load page or i refresh page
But is is not catching when i call api throw angular resourse.
I tried AJAX call configuration as posted in documentation but still not working.
In config file:-
/*
|--------------------------------------------------------------------------
| Capture Ajax Requests
|--------------------------------------------------------------------------
|
| The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
| you can use this option to disable sending the data through the headers.
|
*/
'capture_ajax' => true,
And In My Controller:-
Debugbar::addMessage('Another message', 'mylabel');
Debugbar::warning('Watch out..');
Debugbar::sendDataInHeaders();
-ND

After searching longtime on web i got solution for this problem
Kindly add this code to your app.js
.factory('httpInterceptor', function($q) {
var handle_phpdebugbar_response = function(response) {
if (phpdebugbar && phpdebugbar.ajaxHandler) {
var headers = response && response.headers && response.headers();
if (!headers) {
return;
}
var headerName = phpdebugbar.ajaxHandler.headerName + '-id';
var debugBarID = headers[headerName];
if (debugBarID) {
phpdebugbar.loadDataSet(debugBarID, ('ajax'));
}
}
};
return {
request: function(config) {
return config || $q.when(config);
},
response: function(response) {
if (response || $q.when(response)) {
handle_phpdebugbar_response(response);
return response || $q.when(response);
}
},
responseError: function(response) {
handle_phpdebugbar_response(rejection);
return $q.reject(response);
}
};
})
.config(function($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
})
This one is in angular module ng-phpdebugbar

(Laravel5)
Instead of returning your response, send it to a view:
return \View::make('debug', ['data' => $response]);
instead of
return response()->json($response);
(don't forget to create the view where you echo your data)

Related

AngularJS - Unauthorized and interceptors

Im working with angularjs and Im trying to handle errors with interceptors.
I have run into the issue of how handling the different error session expires with login failed when server replies both with 401.
It seems that interceptors defined in the config will execute before any other interceptors (order definition matters):
var configInterceptor = function($httpProvider)
{
$httpProvider.interceptors.push('unauthorizedInterceptor');
};
angular.module('app', [])
.config(configInterceptor)
.controller....
The interceptors defined in the $resource will be considered only after they have gone through the configInterceptor.
var res = $resource(serviceUrl + '/users/login',{},{
post:{
method:'POST',
params: {},
withCredentials: true,
interceptor: {
responseError: function(){
console.log('login interceptor');
}
}
}
});
I would like to have a single point for controlling when the session has expired (pushing the user to the login page and sending an appropriate message) without the need to add the unauthorizedInterceptor to all $resources, one by one.
If the error is due to users trying to log in and failed, then the interceptor should treat it differently (message will be different).
Any way to resolve this properly? I tried also defining interceptors to only be applied to a specific module but they are triggered.
I would do something like that:
angular.module('app', []).factory('unauthorizedInterceptor', unauthorizedInterceptor);
function unauthorizedInterceptor($q, ngUserAuthService) {
return {
'responseError': function (response) {
if (response.status === 401) {
// find out if the session has expired or the user login has failed
if (sessionExpired()) {
doRedirectToSomewhere();
} else if (loginHasFailed()) {
response.loginFailed = true; // use this later
}
}
return $q.reject(response);
}
};
}
And then only add an interceptor to the $resource when you want to check for failed login:
var res = $resource(serviceUrl + '/users/login',{},{
post:{
method:'POST',
params: {},
withCredentials: true,
interceptor: {
responseError: function(response) {
console.log('login interceptor');
console.log('The login has failed: ' + response.loginFailed);
}
}
}
});

angular request busy interceptor

UPDATE
I think I solved it myself. Check my interceptor that I posted as a solution below.
ORIGINAL
I was wondering if it would be possible to write an http interceptor that can let the caller know how the request is doing.
Right now, when I want to call my backend, I wrap an $http call in a wrapper that sets attributes on an object I pass it:
publ.wrap = function(f, ctrl){
ctrl.busy = true;
ctrl.error = false;
return f()
.then(function(res){
ctrl.busy = false;
ctrl.result = res;
return res;
}).catch(function(err){
ctrl.busy = false;
ctrl.error = err;
ctrl.result = undefined;
})
};
publ.login = function(args, ctrl){
publ.wrap(function(){
return $http.post('http://localhost:3001/authenticate', {
username : args.username,
password : args.password
}).then(function(jwt){
$cookies.put('token', jwt);
})
}, ctrl);
};
In this case, I call login(authArgs, $scope.loginCtrl) in my login page controller. Then I use loginCtrl.busy, loginCtrl.result & loginCtrl.error in my login template.
I pretty much want every call I make to the backend to set these attributes and make them available to the views that initiate the request.
Using a wrapper function like this gets the job done, but I'm wondering if it can be done using an interceptor? It feels to me like that would provide a much cleaner request flow that doesn't require me to explicitly wrap all of my backend calls in my services.
Now I read up on httpInterceptors, and can't seem to find a way to have them set attributes on a user-provided object. The closes thing I found was this article that has an example ( Timestamp Marker (request and response interceptors) ) where they add attributes to the config object in both the request and response interceptor stages.They don't show how to access the config object inside the responseError stage or in the caller controller.
Any help would be greatly appreciated :)
I use Angular events to handle stuff like this- for example:
.controller('parentCtrl', function($scope,$rootScope) {
$rootScope.$on('loading',function(e,_statusObj.loading) {
$scope.loading = _statusObj.loading;
if(!!_statusObj.msg) {
alert(_statusObj.msg);
}
});
})
.controller('childCtrl', function($scope,$http) {
$scope.myAjaxCall = function(_url,_data) {
$scope.$emit('loading',{ loading: true});
$http.post(_url,_data).success(function(_response) {
$scope.$emit('loading',{ loading: false });
})
.error(function(_error) {
$scope.$emit('loading',{
loading : false,
msg : _error.message
});
});
}
});
I managed to get the interceptor working. Apparently we CAN access the config file in all interceptor phases:
/******************************************
SETUP BUSY/ERROR/DATA HTTP INTERCEPTOR
*******************************************/
.config(function($httpProvider){
$httpProvider.interceptors.push(function($q) {
return {
request : function(config) {
if(config.ctrl){
config.ctrl.busy = true;
config.ctrl.error = false;
config.ctrl.data = undefined;
}
return config;
},
response : function(response) {
if(response.config && response.config.ctrl){
response.config.ctrl.busy = false;
response.config.ctrl.data = response.data;
}
return response;
},
responseError : function(response){
// note: maybe use a different error message for different kinds of responses?
var error = response.status + " "+response.statusText+" - "+response.data;
if(response.config && response.config.ctrl){
response.config.ctrl.busy = false;
response.config.ctrl.error = error;
}
return $q.reject(error);
}
};
});
})

Ionic : no content / white screen using interceptors

I successfully managed to use interceptors (AngularJs ) in my Ionic application. Previous post .
While it is working perfectly well in the browser using "ionic serve".
There is no content loaded in the header title and content block ( "ion-content" ) using "ionic run android" (either emulating on genymotion or on my own phone). See screenshot below.
I'm pretty sure it comes from the interceptors i'm using, because before that, the app was working on any platforms. Also, as soon as i remove the interceptors it is working again. Here the code.
Note that i'm checking which url is called so i don't go into a circular dependency or checking useless url, only the calls to my api go through.
app.config(function($httpProvider){
$httpProvider.interceptors.push(['$location', '$injector', '$q', function($location, $injector, $q){
return {
'request' : function(config){
// intercept request
// carefull includes might not work while emulating
// use instead indexOf for that case
if(!config.url.includes('/oauth/v2/token') && config.url.includes('/api')){
// inject the service manually
var OauthService = $injector.get('OauthService');
var access_token = OauthService.token();
config.url = config.url+'?access_token='+access_token.key;
}
return config;
}
}
}]);
});
Any ideas what could give this error? (By the way console is showing no errors on browser).
UPDATE :
OauthService.js :
app.factory('OauthService', function($http, $localStorage) {
return {
token : function(){
// Store actual token
access_token = $localStorage.getObject('access_token');
// Store actual identity
identity_token = $localStorage.getObject('identity_token');
// IF no user logged
if(isObjectEmpty(identity_token)){
// IF access_token does NOT exist OR will expires soon
if( isObjectEmpty(access_token) || Date.now() > (access_token.expires_at - (600*1000)) ){
// Create an anonymous access_token
return $http
.get(domain+'/oauth/v2/token?client_id='+public_id+'&client_secret='+secret+'&grant_type=client_credentials')
.then(function (response) {
$localStorage.setObject('access_token', {
key: response.data.access_token,
type: 'anonymous',
expires_at: Date.now()+(response.data.expires_in*1000)
});
return response.data.access_token;
});
}
}
// IF user is logged
else{
// IF access_token does NOT exist OR will expires soon OR is anonymous
if( isObjectEmpty(access_token) || Date.now() > (access_token.expires_at - (600*1000)) || access_token.type == 'anonymous' ){
// Create an access_token with an identity
return $http
.get(domain+'/oauth/v2/token?client_id='+public_id+'&client_secret='+secret+'&api_key='+identity_token+'&grant_type=http://oauth2.dev/grants/api_key')
.then(function (response) {
$localStorage.setObject('access_token', {
key: response.data.access_token,
type: 'identity',
expires_at: Date.now()+(response.data.expires_in*1000)
});
return response.data.access_token;
});
}
}
return access_token.key;
}
};
})
Did you install cordova whitelist plugin ?
cordova plugin add cordova-plugin-whitelist
or if you want to save the reference to your config.xml file:
cordova plugin add cordova-plugin-whitelist --save
If you don't have that your device won't be able to access external resources.
You can find more info here.
UPDATE:
I've checked your previous answer.
The idea of the interceptor is to intercept calls to an external service insert some action in the pipeline.
I would change your interceptor:
$httpProvider.interceptors.push(['$location', '$injector', '$q', '$localStorage', function($location, $injector, $q, $localStorage){
return {
'request' : function(config) {
config.headers = config.headers || {};
access_token = $localStorage.getObject('access_token');
if (access_token) {
config.headers.Authorization = 'Bearer ' + access_token;
}
}
'response' : function(response){
if (response.status === 401) {
logger.debug("Response 401");
}
return response || $q.when(response);
}
'responseError' : function(rejection){
if (rejection.status === 401) {
var OauthService = $injector.get('OauthService');
var access_token = OauthService.token();
if (access_token === null)
{
return $q.reject(rejection);
}
// Append your access token to the previous request and re-submits.
rejection.config.headers['Authorization'] = 'Bearer ' + access_token;
return $injector.get('$http')(rejection.config);
}
// This is necessary to make a `responseError` interceptor a no-op.
return $q.reject(rejection);
}
}
}]);
If you look at the interceptor above it manages all the requests to an external resource (REST api) and appends a bearer token to the authorization header if needed.
The response does not do much as it is only there for logging purposes.
responseError is the place where you should intercept and check if your token as expired, fetch a new one and resubmit the request.
We check if the user is not authorized to the request:
if (rejection.status === 401) { ... }
If not we request a new access token. I guess your OauthService does that.
If we have a new access token:
var access_token = OauthService.token();
we can, again, append the access token to the request header:
rejection.config.headers['Authorization'] = 'Bearer ' + access_token;
and resubmit the previous request:
return $injector.get('$http')(rejection.config);
If you want to find out more about interceptors you can read these blogs.

ng mock e2e Unexpected Request

I'm using the ngMockE2E to mock the httpBackend while developing the UI in Angular JS. The App runs on a Grizzly-Server with a backend which is provided by a virtual machine. Now when I go on the Website the Console logs the Error:
Unexpected request: GET /api/info
No more request expected
In my case I only want to mock the data of one database. Additional to that I want to turn the mock ON/OFF on the fly via a button. This was working until the Error comes up.
For that case I've written the following:
$httpBackend.whenPOST(function (url) {
if (!mockup) {
return false;
}
var target_url = (someUrl);
return target_url === url;
}).respond(function (method, url, data) {
return [200, [someData], {}, 'mockupData'];
}
);
Additional to that I've added the following to pass all the other requests:
// pass the rest of the queries
$httpBackend.whenGET(/.*/).passThrough();
$httpBackend.whenPOST(/.*/).passThrough();
$httpBackend.whenPUT(/.*/).passThrough();
$httpBackend.whenDELETE(/.*/).passThrough();
So for all of you who face the same problem. I found a workaround for the issue. But I'm sure there should be another better solution.
For that I used an Interceptor which is also provided by angular. Here the api
So I wrote this:
app.factory('httpInterceptor', function () {
return {
'response': function (response) {
// therefore you can enable the mockup with a switch or a button
if (!mockup) {
return response;
}
try {
// in the config object is the requested url
if (response.config.url !== someUrl) {
// don't intercept; return response unchanged
return response;
}
// found an url which should be mocked
// generate or modify the data
var generatedData = generateSomeData();
response.data.push(generatedData)
return response;
} catch (TypeError) {
// don't intercept
return response;
}
}
}
}
);
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('httpInterceptor');
}]);

Set different $http url prefix for template and server requests

Basically what I'm trying to do is to set a prefix for all $http server requests (the server url). I tried to use an interceptor, but the problem is that this also affects the template requests:
$httpProvider.interceptors.push(function ($q) {
return {
'request': function (request) {
request.url = "http://localhost/"+request.url;
return request || $q.when(request);
}
}
});
=>
XMLHttpRequest cannot load http://localhost/templates/main.html
I thought about using my own provider (for example $myHttp) which inherit $http, but i don't know how to do this.
So what is a good solution for this?
If all of your templates are in the templates directory, you could just ignore those in your interceptor.
$httpProvider.interceptors.push(function ($q) {
return {
request: function (request) {
if (request.url.indexOf('templates') === -1) {
request.url = "http://localhost/" + request.url;
}
return request || $q.when(request);
}
}
});

Resources