Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
git clone https://github.com/angularsumitg/angular2-quickstart.git my-proj
cd my-proj
npm install
npm start

...

 

Code Block
<topology><service><url>http://localhost:3000

  • This populates the data used by {$serviceUrl[EXAMPLEUI]} in the rules with the correct target URL.

 

 

Taking care of slash’ness

So now the question of the trailing slash comes in. With that comes the opportunity to talk about rewriting parts of the body of the response. 
So again, the goal is to get this URL to work (no trailing slash)
The problem is that the page has links as the ones below (this can be seen by viewing the page source in the browser).
Code Block
<link rel="stylesheet" href="styles.css">

<!-- Polyfill(s) for older browsers -->

<script src="node_modules/core-js/client/shim.min.js"></script>

<script src="node_modules/zone.js/dist/zone.js"></script>

<script src="node_modules/reflect-metadata/Reflect.js"></script>

<script src="node_modules/systemjs/dist/system.src.js"></script>

<script src="systemjs.config.js"></script> 
All these ‘href' and ‘src' tags work great if the main page is at the root of the URL, like http://localhost:3000, but once you have a path in the URL like the additional path needed by the gateway e.g. ‘gateway/sandbox/example’ then they don’t resolve too well without the slash. For instance, href=“styles.css” without the trailing slash will resolve to 
To remedy this, we are going to rewrite these ‘href' and ‘src’ tags so that path is fully qualified i.e. styles.css should become ‘/gateway/sandbox/example/styles/css’.
Here are the new rules we need.

new rewrite.xml rules

 
Code Block
<rule dir="OUT" name="EXAMPLEUI/exampleui/outbound/systemjs" pattern = "systemjs.config.js">
    <rewrite template="{$frontend[path]}/example/systemjs.config.js"/>
</rule>
<rule dir="OUT" name="EXAMPLEUI/exampleui/outbound/styles" pattern="styles.css">
    <rewrite template="{$frontend[path]}/example/styles.css"/>
</rule>
<rule dir="OUT" name="EXAMPLEUI/exampleui/outbound/nodemodules" pattern="node_modules/{**}">
    <rewrite template="{$frontend[path]}/example/node_modules/{**}"/>
</rule>
 
Now the rules include rewriting the response in the OUTBOUND direction, going out from Knox to the browser. These rules leverage a Rewrite function $frontend[path] to get the ‘/gateway/sandbox’ portion of the URL.
Please note that every time you change the rewrite or service files you need to redeploy the topology. This can be either done by touching the topology file or by deleting the deployed topology directory and restarting Knox.
Now the links shown previously for the main page should look like this:
Code Block
<link rel="stylesheet" href="/gateway/sandbox/example/styles.css">

<!-- Polyfill(s) for older browsers -->

<script src="/gateway/sandbox/example/node_modules/core-js/client/shim.min.js"></script>

<script src="/gateway/sandbox/example/node_modules/zone.js/dist/zone.js"></script>

<script src="/gateway/sandbox/example/node_modules/reflect-metadata/Reflect.js"></script>

<script src="/gateway/sandbox/example/node_modules/systemjs/dist/system.src.js"></script>

<script src="/gateway/sandbox/example/systemjs.config.js"></script> 
The page however still doesn’t render correct. This is because while we can now load the JS files, they contain unresolvable paths in the javascript itself. If this were a static page of old, we would be done a while ago!
By navigating to the URL https://localhost:8443/gateway/sandbox/example/systemjs.config.js you can see the issue being in this snippet:
Code Block
...
 System.config({
    paths: {
      // paths serve as alias
      'npm:': 'node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the apps folder
      app: 'apps',
...
Both ‘node_modules/‘ and ‘apps’ needs the proper context. Lets go back to the rewrite file and fix this.

Final rewrite.xml changes

Here are the final additions you need. A neat trick here is the use of a Rules Filter to contain the rules to the content type of javascript.
Here is the final file Rewrite File
Code Block
<rule dir="OUT" name="EXAMPLEUI/exampleui/outbound/apps">
    <rewrite template="example/apps"/>
</rule>
<rule dir="OUT" name="EXAMPLEUI/exampleui/outbound/nodemodule">
    <rewrite template="example/node_modules"/>
</rule>

<filter name="EXAMPLEUI/exampleui/outbound/app">
    <content type="application/javascript">
        <apply path="apps" rule="EXAMPLEUI/exampleui/outbound/apps"/>
        <apply path="node_modules" rule="EXAMPLEUI/exampleui/outbound/nodemodule"/>
    </content>
</filter>


Tying it back to service.xml

The filter needs to be tied back to the service file. So now the service file looks like this in its entirety.
Here is the final file Service File
 
Code Block
<service role="EXAMPLEUI" name="exampleui" version="0.0.1">
    <policies>
        <policy role="webappsec"/>
        <policy role="authentication" name="Anonymous"/>
        <policy role="rewrite"/>
        <policy role="authorization"/>
    </policies>
    <routes>
        <route path="/example">
        </route>
        <route path="/example/**">
            <rewrite apply="EXAMPLEUI/exampleui/outbound/app" to="response.body"/>
        </route>
    </routes>
    <dispatch classname="org.apache.hadoop.gateway.dispatch.PassAllHeadersDispatch"/>
</service>
 

Now the page should load up fine. If you were to check the JS snippet now, you should see this
Code Block
...
 System.config({
    paths: {
      // paths serve as alias
      'npm:': 'example/node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the example/apps folder
      app: 'example/apps',

... 

 

...