Skip to Content
Technical Articles
Author's profile photo Nicolai Geburek

SAP Tech Bytes: Serve Web Page with an Approuter – Cloud Foundry Basics #2

This SAP Tech Byte is about how to use an approuter on Cloud Foundry to serve a web page. We will use the approuter to authenticate users and route them to the web page.

 

Building on top of the first blog post of this “Cloud Foundry Basics” series, which covered deploying a static web page, we will deploy an approuter to the SAP Business Technology Platform, Cloud Foundry environment today. The approuter allows us to also serve an index.html (as in the previous post) but with the added benefit of being able to authenticate users and route them to the web page. There is a lot more an approuter can do, but we will stick with these basics for now.

 

The Web Page

First, we need an index.html file (our web page). I created a very simple UI5 app that displays a MeessagePage and, more interestingly, fetches information about the logged in user from the /user-api/ endpoint, which the approuter provides. We will get into that next.

<!DOCTYPE html>
<html>

<head>
    <script
        id="sap-ui-bootstrap"
        src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
        data-sap-ui-theme="sap_horizon"
        data-sap-ui-libs="sap.m"
    ></script>
    <script defer>
        fetch("/user-api/currentUser")
            .then(response => response.json())
            .then(data => {
                let user = data

                sap.ui.jsview("my.view", {
                    createContent: function (oController) {
                        return new sap.m.MessagePage({
                                    title:  `Hello, ${user.firstname}!`,
                                    text: "Bear with us.",
                                    description: "This application is work in progress.",
                                    icon: "sap-icon://wrench"
                                })
                    }
                })

                var app = new sap.m.App({
                    initialPage: "mainPage"
                })
                var page = sap.ui.view({
                    id: "mainPage",
                    viewName: "my.view",
                    type: sap.ui.core.mvc.ViewType.JS
                })
                app.addPage(page)
                app.placeAt("content")
            })
    </script>
</head>

<body class="sapUiBody" id="content"></body>

</html>

 

The Approuter

We will use an approuter, which is essentially a node.js based application (npm package), to authenticate users and route them to our web page. The approuter expects an xs-app.json file describing its routing behaviour. We create this file and put it next to your index.html:

{
    "welcomeFile": "index.html",
    "authenticationMethod": "route",
    "routes": [
      {
        "source": "^/user-api(.*)",
        "target": "$1",
        "service": "sap-approuter-userapi"
      },
      {
        "source": "^(.*)$",
        "target": "$1",
        "authenticationType": "xsuaa",
        "localDir": "./"
    }
    ]
  }

The xs-app.json describes the routing behavior of the application. We defined the welcomeFile as well as the authenticationMethod. The routes array is the most interesting part:

  1. The first route is linked to the sap-approuter-userapi service, which the approuter provides since version 9 (learn more about this service API in this blog post). Defining the route means that whenever we call the URL of our approuter and attach a string that matches the regex pattern of the source (“^/user-api(.*)”), the approuter will forward all request to the defined service. The sap-approuter-userapi service provides information about the logged in user, which we use to greet the user of our web page (see the title of the MessagePage).
  2. The second route points to a localDir (local directory) and in combination with the welcomeFile, forwards all requests (regex pattern “^(.*)$”) that didn’t hit the first route to our index.html. To put it into simpler words, the approuter serves the web application. We also configured the authenticationType to be xsuaa, which will make sense once we bind our app to the Authorization & Trust Management service (short “xsuaa”) on Cloud Foundry. This means all users of the approuter will need to login with this service to get to our web page.

Our approuter is a node.js based application, which means we need a package.json file describing the application and its dependencies (only one in this case). We create the following file on root level of the project (next to all other files):

{
    "name": "my-approuter",
    "scripts": {
      "start": "node node_modules/@sap/approuter/approuter.js"
    },
    "dependencies": {
      "@sap/approuter": "^9"
    }
  }

By the way: The approach we are following here with our approuter is also referred to as a “standalone approuter”. You can read about the differences between a standalone and managed approuters in this blog post.

 

Deployment Configuration

To be able to deploy our approuter to Cloud Foundry (cf push), we need a manifest.yaml file as our deployment descriptor. We create this file on root level of the project:

---
applications:
- name: my-web-page
  buildpack: https://github.com/cloudfoundry/nodejs-buildpack
  services:
  - my-xsuaa

This file is very similar to the one we used in the previous blog post, but two things are different:

  1. We changed the buildpack from staticfile-buildpack to nodejs-buildpack, as we are now pushing a different kind of application.
  2. We added a service instance called my-xsuaa to the deployment descriptor, which makes sure our app will be bound to this service instance during the deployment. This means that before we can deploy our application, we have to create this service instance in our Cloud Foundry space manually, which we will do next.

 

Authorization & Trust Management service

Before we can create an instance of the Authorization & Trust Management service in our Cloud Foundry space, which will later be bound to our approuter, we first have to provide a minimal configuration file for this instance. We create the following xs-security.json file on root level of the project:

{
    "xsappname": "my-xsuaa",
    "tenant-mode": "dedicated"
}

 

After logging in to our Cloud Foundry space (with the command cf login), we can run the following command to create the instance of the Authorization & Trust Management service in our space.

cf create-service xsuaa application my-xsuaa -c xs-security.json

Notice that the name of the instance (my-xsuaa) matches the configuration in our manifest.yaml file (necessary for the binding).

We can already see the instance in our Cloud Foundry space:

SAP%20BTP%20Cockpit

Deployment

Next, we can deploy our application to the SAP BTP, Cloud Foundry environment. We should already be logged in to our space. We can execute the cf push command to start the deployment process. The process may take a minute or two. Once it’s done, we can see the URL of the application in the terminal output:

terminal%20output

When opening the URL, you will notice that you are being redirected to a login page. You can login with the same credentials you use to login to your SAP BTP account. You might get logged in with Single-Sign-On, in which case the login is hardly noticeable, but you can be sure you are logged in if you see your name being displayed in the UI5 app:

logged%20in%20user

 

And that’s it. We have deployed an approuter, which is authenticating users and serving a web page to the SAP BTP, Cloud Foundry environment.

Feel free to reach out in case you have any questions.

Stay tuned for more blog posts covering the basics of Cloud Foundry.

 


sap-tech-bytes

 

 

 

 

SAP Tech Bytes is an initiative to bring you bite-sized information on all manner of topics, in video and written format. Enjoy!

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.