Search code examples
angularjsrestproxydelegationmicroservices

How do I create a delegating Angular multi host site?


I work in an environment where we develop a solution using several (a lot of) servers. They microservice style is the role model.

To be able to upgrade systems they must be switchable/replaceable (including the user interface) in runtime. The principal solution that have been decided upon is that

  1. a Portal/Proxy is the only visible system for the end user
  2. The proxy is "aware" af the supporting servers
  3. The proxy has some basic user interface with for instance menues. Might be in collaboration with the subsystems (several entries in the menu etc.)
  4. A user requests a page with some dynamic content
  5. The portal relays/proxy the query of "content" part of the page to the subsystem.
  6. Any REST-calls needed by the client is also proxied through the main server.

The REST calls are of course very simple but I am too n00b in Angular to really understand how to make the "mix. Point number 5 is of course the tough part. IF the subserver would have been visible an iframe (eeek!) could have been used but not in this case.

I need some sort of "delegation" within a page, anything done before? How DOES the microservice flagships handle the User Interface?


Solution

  • I have now evolved from n00b to n00b++ regarding Angular.

    The solution lies within the HTML-snippets used for templates within Angular.

    I can define a html template with a JS file and an HTML file. The JS file refers to the HTML page by a URL. Usually (in the samples I have seen) the path is relative like:

    angular.module('myApp.view1', ['ngRoute'])
    .config(['$routeProvider', function($routeProvider) {
      $routeProvider.when('/view1', {
        templateUrl: 'view1/view1.html',
        controller: 'View1Ctrl'
      });
    }])
    .controller('View1Ctrl', [function() {}]);
    

    But by using an absolute path I can refer to an external resource:

    angular.module('myApp.view2', ['ngRoute'])

    .config(['$routeProvider', function($routeProvider) {
      $routeProvider.when('/view2', {
        templateUrl: host + '/app/view2/view2.html',
        controller: 'View2Ctrl'
      });
    }])
    .controller('View2Ctrl', [function() {}]);
    

    Notice I added a parameter 'host' calculated by looking at the script tag including this JS file.

    var scripts = document.getElementsByTagName('script');
    var src = scripts[scripts.length - 1].src;
    var host = src.match(new RegExp('https?://[^/]*'))[0];
    

    But the third problem to address is to handle the CORS problem. In my test environment (node.js+express) I just added the 'cors' library and I could access my "external" site.

    var express = require('express'), 
        cors = require('cors'), 
        app = express();
    
    app.use(cors());
    app.use("/", express.static(__dirname));
    
    app.listen(8001, function(){
        console.log('CORS-enabled web server listening on port', 8001);
    });