Angular web app routing within Juniper SSL VPN

3.3k views Asked by At

Currently I am working on a simple web app, using AngularJS. During the development process, I tested it while the app was locally served by IIS. However, when I deployed it on a company web server and ran it within a Juniper SSL VPN the trouble began.

First I had to apply the following 'fix': AngularJS Routing Fails when running within a Juniper SSL VPN #8905

But the above fix only solved part of the trouble. The problem that remains is that AngularJS returns the following error when I try to load an other than the default ('/') view ($location.path('/anotherView') from the view controller, I get the following error message:

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations: []
http://errors.angularjs.org/1.3.15/$rootScope/infdig?p0=10&p1=%5B%5D
    at REGEX_STRING_REGEXP (,DanaInfo=server1.mydomain.nl,CT=js+angular.js:63)
    at Scope.$get.Scope.$digest (,DanaInfo=server1.mydomain.nl,CT=js+angular.js:14340)
    at Scope.$get.Scope.$apply (,DanaInfo=server1.mydomain.nl,CT=js+angular.js:14565)
    at done (,DanaInfo=server1.mydomain.nl,CT=js+angular.js:9685)
    at completeRequest (,DanaInfo=server1.mydomain.nl,CT=js+angular.js:9875)
    at XMLHttpRequest.requestLoaded (,DanaInfo=server1.mydomain.nl,CT=js+angular.js:9816)(anonymous function) @ ,DanaInfo=server1.mydomain.nl,CT=js+angular.js:11649$get @ ,DanaInfo=server1.mydomain.nl,CT=js+angular.js:8583$get.Scope.$apply @ ,DanaInfo=server1.mydomain.nl,CT=js+angular.js:14567done @ ,DanaInfo=server1.mydomain.nl,CT=js+angular.js:9685completeRequest @ ,DanaInfo=server1.mydomain.nl,CT=js+angular.js:9875requestLoaded @ ,DanaInfo=server1.mydomain.nl,CT=js+angular.js:9816

I've tested it with the default AngularJS Routing and the Angular ui.router mechanism and both give the same result.

Any help to solve this problem is really appreciated!

3

There are 3 answers

0
André Bakker On BEST ANSWER

Problem is solved by configuring Juniper to act as a reversed proxy.

1
tdhulster On

We solved this problem by patching the parseAppUrl function in the core Angular.js codebase as following :

function parseAppUrl(relativeUrl, locationObj, appBase) {
  var prefixed = (relativeUrl.charAt(0) !== '/');
  if (prefixed) {
    relativeUrl = '/' + relativeUrl;
  }
  var match = urlResolve(relativeUrl, appBase);
  locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
      match.pathname.substring(1) : match.pathname);
  locationObj.$$search = parseKeyValue(match.search);
  locationObj.$$hash = decodeURIComponent(match.hash);

  //Detect Juniper re-write functions and handle the $$path issue
  if(locationObj.$$path === "[object Object]" && typeof(DanaOrigUrl) === 'function') {
    var __strH = 'href';
    var __tmpHack = match[__strH];
    var __nn = ("" + __tmpHack).match(/^(https?:\/\/[^\/]+)?([^?|#]*)/);
    locationObj.$$path = __nn[2];
  }
  // make sure path starts with '/';
  if (locationObj.$$path && locationObj.$$path.charAt(0) != '/') {
    locationObj.$$path = '/' + locationObj.$$path;
  }
}

Reference : https://github.com/angular/angular.js/issues/8905

0
Alexander Bering On

In my case, I had issues with the rewriting of URLs. The gateway did it pretty well with standard HTML href attributes, but not for the Angular AJAX calls. So I wrote an interceptor to do the trick:

Angular 2 (JavaScript)

app.config( function( $httpProvider ) {
  $httpProvider.interceptors.push( function( $q, $rootScope ) {
    return {
      'request': function( config ) {
        // Convert request URL for Juniper Secure Web Access
        if ( typeof DanaUrl === "function" && !config.url.includes( '.html' ) ) {
          config.url = DanaUrl( config.url );
        }
        return config;
      }
    };
  } );
} );

Angular 5+ (TypeScript)

import { Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor, HttpResponse, HttpErrorResponse, HttpHeaders } from '@angular/common/http';

declare function DanaUrl(url: string): string;

@Injectable()
export class CustomHttpInterceptor implements HttpInterceptor {
constructor(
) { }

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    // Rewrite Juniper SWA URLs
    if ( typeof DanaUrl === "function" && !request.url.includes( '.html' ) ) {
        request = request.clone({
            url: DanaUrl( request.url )
        });
    }

    return next.handle(request).do((event: HttpEvent<any>) => {
        if (event instanceof HttpResponse) {
            // do stuff with response if needed
        }
    }, (err: HttpErrorResponse) => {

    }).finally(() => {

    });
}

}

The URLs will be rewritten, if the Juniper's DanaURL function is available and the URL does not include with ".html". That is because Angular uses URLs to include views into the template, even they are included (e.g. in script tags). (I don't like this part, but for now it's working...)

I hope it's helpful for someone...