Skip to Content
Technical Articles
Author's profile photo Luisa Grigorescu

Destination Service – How It Can Be Used?

In this blog post I will show you how to connect a SAPUI5 app with an external backend service with the help of an approuter and the destination service.

 

What is it?

The destination serivce, as the name calls it, allows you to get from point A to point B. A could be a SAPUI5 app and B an ABAP system that resides somewhere in an on-prem system.

 

What are the use cases?

Usually A represents an app that resides inside of Cloud Foundry and B is a remote system (like an on-prem system or an application outside of Cloud Foundry). The destination service can also be used for accessing apps inside of Cloud Foundry.

 

How it can be used?

  • for connections with on-prem systems; you need to bind a connectivity service and a destination service to your application router
  • for connections with web apps; you need a destination service instance binded to your approuter without the connectivity service

 

Example of an application router config for a SAPUI5 app that needs to access an on-prem system.

 

Before listing a manifest.yaml sample file, let’s dive a bit into it’s structure.

  • name: this is how you’ll find the app listed in the target space
  • host:  URL service name, which needs to be unique across the entire domain. It will be in the form https://<host>.cfapps.sap.hana.ondemand.com
  • buildpack: technology stack. You can see the list of all the available buildpacks by executing the cf buildpacks command in a terminal.
  • memory, disk_quota: how much memory and disk space you want to allocate to your app
  • path: where the app resides. This needs to be relative to the manifest.yaml file location.
  • env: user-defined system variables, that can be accessed from within the app. In here you need to defined the destinations. They define the URL to which requests are forwarded. The value of the destination “name” property (“name”:“sapui5-app-ui” in the example below) must match the value of the destinations property configured for a route in the corresponding application-router configuration file (xs-app.json).
  • services: what service instances from your target account need to be bound to this app?

 

manifest.yaml

applications:
    - name: on-prem-approuter
      host: on-prem-approuter-t4257
      buildpack: nodejs_buildpack
      memory: 128M
      disk_quota: 512M
      path: ./
      env:
        CORS: >
          [{
             "allowedOrigin": [{"host":"*"}],
              "uriPattern": "^\/(retail-service).*$",
              "allowedMethods": ["GET", "POST", "PUT", "HEAD", "OPTIONS", "DELETE", "PATCH"]
           }]
        TENANT_HOST_PATTERN: "^(.*)-approuter-t4257.cfapps.eu10.hana.ondemand.com"
        destinations: >
          [
            {"name":"sapui5-app-ui", "url" :"https://sapui5-app.cfapps.eu10.hana.ondemand.com", "forwardAuthToken": true },
          ]
      services:
        - approuter-uaa
        - connectivity-abap
        - destination-abap

  

Let’s dive into the purpose and structure of an xs-apps.json before listing it.

 

The application router is used to serve static content, authenticate users, rewrite URLs, and forward or proxy requests to other micro services while propagating user information. The application-router configuration file xs-app.json configures the application router and describes the routes. 

 

Every route configuration that forwards requests to a micro service has property destination. The destination is a name that refers to the same name in the destinations configuration. The destinations configuration is specified in an environment variable passed to the approuter application or configured in the target account as seen in an image from below.

 

xs-app.json

{
    "welcomeFile": "index.html",
    "authenticationMethod": "route",
    "routes": [
      {
        "source": "/sapui5-ui(.*)",
        "target": "$1",
        "destination": "sapui5-ui-app",
        "authenticationType": "xsuaa"
      },
      {
        "source": "/retail-service(.*)",
        "target": "/sap/opu/odata/sap/ZSCPRS_CAR_SRV/$1",
        "destination": "ABAP_Destination",
        "authenticationType": "xsuaa"
      },
      {
        "source": "/(.*)",
        "localDir": "resources",
        "authenticationType": "xsuaa",
        "cacheControl": "public, max-age=1000,must-revalidate",
        "replace": {
          "pathSuffixes": [
            "index.html"
          ]
        }
      }
    ]
 }

Notes: The ABAP_Destination is the destination configured in the SCP account to point to the on-prem.

 

Here is a sample of how it looks like in SCP:

 

 

Sample of application router config for a SAPUI5 app that needs access to a S/4 HANA Cloud – web app:

 

manifest.yaml

applications:
  - name: webapp-approuter
    host: webapp-approuter-t4257
    buildpack: nodejs_buildpack
    memory: 128M
    disk_quota: 512M
    path: ./
    env:
      destinations: >
        [
          {
            "name":"webapp_api",
            "url":"https://webapp-backend.cfapps.eu10.hana.ondemand.com",
            "forwardAuthToken": true
          }
        ]
    services:
          - xsuaa-service
          - dest-service
          - html5-repo-runtime   

xs-app.json

{
    "welcomeFile": "index.html",
    "authenticationMethod": "route",
    "routes": [
        {
            "source": "^/srv/(.*)",
            "target": "$1",
            "destination": "webapp_api",
            "authenticationType": "xsuaa",
            "csrfProtection": false,
            "scope": [
                "$XSAPPNAME.create-condition-records"
            ]
        },
        {
            "source": "^(.*)$",
            "target": "$1",
            "service": "html5-apps-repo-rt",
            "authenticationType": "xsuaa",
            "scope": [
                "$XSAPPNAME.create-condition-records"
            ]
        }
    ]
}

Troubleshooting

 

400 – Bad Request

  • Make sure that your requests sent from SAPUI5 are serialized before sending the requests via the destination service. Use JSON.stringify(req)

 

403 – Forbidden

  •  In case you have an ABAP system, make sure that you have configured the a technical user with the appropriate rights in the destination service.
  • In case you have a web app application you can try setting the “csrfProtection”: false (due to security concerns this property should be used as minimal as possible)
  • Make sure you have the x-csrf-token present for any POST/PUT/DELETE/UPDATE request. For having it in the header you need to do a GET it with x-csrf-token: fetch. The get can be any URI that is from your approuter

 

500 – Internal Server Error

  • If you are trying to access an on-prem system it could be that you are missing a connectivity service instance from your approuter.

 

Summary

In this quick guide you’ve learnt how to connect a SAPUI5 with a backend service that resides outside of Cloud Foundry (on-prem system or web app) via the approuter.

The main point is to understand that you need the connectivity service only when you want to access an on-prem system. Make sure that all the authorization configurations are in place.

 

I’m fairly certain there’s a lot of room for improvements in this blog (as it’s my first one), so I would highly appreciate your feedback in the comments below.

 

What other topics would you like to hear from me? Are there any other topics you would like me to write about? Contact me at luisa.grigorescu@sap.com.

 

My experience is in SAP Cloud Platform, NodeJS, SAPUI5, Java, Spring, Docker, SAP Cloud Application Programming Model, local environment setup, SAP HANA, PostgreSQL.

Assigned Tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Anca Milos
      Anca Milos

      Thank you so much for sharing 🙂

      Author's profile photo Luisa Grigorescu
      Luisa Grigorescu
      Blog Post Author

      Thank you for your feedback! 🙂

      Author's profile photo Calin Lazuran
      Calin Lazuran

      Thank you for the infos, keep doing a great job! 😀

      Author's profile photo Luisa Grigorescu
      Luisa Grigorescu
      Blog Post Author

      Thank you so much Calin! 🙂

      Author's profile photo Florin Pandelea
      Florin Pandelea

      Hi Luisa,

      I found your post really useful, very well structured.

       

      Thanks for sharing !

       

      F

      Author's profile photo Luisa Grigorescu
      Luisa Grigorescu
      Blog Post Author

      Thank you Florin! I highly appreciate your feedback.