Skip to Content
Technical Articles

How to consume on-prem services in public Node.JS API deployed on Cloud Foundry

Introduction

I wanted to create some public API with Node.JS which needs to deploy on Cloud foundry environment. In that I had to consume on-prem service. While consuming on-prem service in unauthenticate Node.JS app, throwing me error as Invaild Proxy Authorization Header. After lot of  search, I figure out the solution for it. So I’m thinking to write solution in one place.

In this blog post will explain you how to connect with on-prem services with Node.JS using XSUAA & Connectivity service instances.

 

Coding

  1. Create package.json file & update with it below code
    {
      "name": "<APP_NAME>",
      "version": "1.0.0",
      "description": "",
      "main": "app.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "node app.js"
      },
      "author": "Prashant Patil",
      "license": "ISC",
      "dependencies": {
        "@sap/xsenv": "^2.2.0",
        "body-parser": "^1.19.0",
        "express": "^4.16.4",
        "request": "^2.88.0",
        "request-promise": "^4.2.5"
      }
    }
    ​
  2. Create manifest.yml file & update with below code
    ---
    applications:
    - name: test-app
      memory: 128M
      instances: 1
      services:
        - test-app-uaa
        - test-app-conn
        ​
  3. Create service instances mentioned in manifest.yml using CF CLI
    cf create-service xsuaa application test-app-uaa​
    cf create-service connectivity lite test-app-conn​
  4. Create app.js & paste below code, We are going connect to the on-prem service through connectivity service instance.
    const express = require('express');
    const rp = require('request-promise');
    const xsenv = require('@sap/xsenv');
    
    //For local run
    //xsenv.loadEnv();
    
    const http = require('http');
    var bodyParser = require('body-parser');
    const app = express();
    var server = http.createServer(app);
    const port = process.env.PORT || 3000;
    var jsonParser = bodyParser.json();
    var urlencodedParser = bodyParser.urlencoded({ extended: false });
    
    const conn_service = xsenv.getServices({ conn: { tag: 'connectivity' } }).conn;
    const uaa_service = xsenv.getServices({ uaa: { tag: 'xsuaa' } }).uaa;
    const sUaaCredentials = conn_service.clientid + ':' + conn_service.clientsecret;
    const proxy_url = 'http://'+conn_service["onpremise_proxy_host"] + ':' + conn_service["onpremise_proxy_port"];
    const onPremCred = '<OnpremSrvUser>:<OnpremSrvUserPassword>';
    
    server.listen(port, () => console.log(`test app listening at http://localhost:${port}`));
    
    app.post('/getDetailsFromOnPrem',jsonParser , (req, res) => {
        return rp({
            uri: uaa_service.url + '/oauth/token',
            method: 'POST',
            headers: {
                'Authorization': 'Basic ' + Buffer.from(sUaaCredentials).toString('base64'),
                'Content-type': 'application/x-www-form-urlencoded'
            },
            form: {
                'client_id': conn_service.clientid,
                'grant_type': 'client_credentials'
            }
        }).then((data) => {
            const token = JSON.parse(data).access_token;
            
            return rp({
                uri: '<on-prem service url>',
                proxy:proxy_url,
                headers : {
                    'Authorization': 'Basic ' + Buffer.from(onPremCred).toString('base64'),
                    'Proxy-Authorization': 'Bearer ' + token,
                    'SAP-Connectivity-SCC-Location_ID':'<Cloud-Connector-Location-Id>',
                    'Content-type': 'application/json'
                }
            });
        }).then((data) => {
            const d = JSON.parse(data);
            res.send(d);
            
        }).catch((error) => {
            res.send(error);
    });​
  5. Deploy app to CF
    cf push test-app​

 

Note:

if you have only one connector without location Id (default) in your sub-account, then do not provide ‘SAP-Connectivity-SCC-Location_ID’ as header.

If you have multiple Cloud connectors added in your sub-account then ‘SAP-Connectivity-SCC-Location_ID’  header is must else it will trying connect with default cloud connector.

 

 

Conclusion

In this blog post you learned how to consume on-premise services in unauthenticated Node.JS app deployed on CF.

 

Hope this helps!

 

 

Prashant Patil

 

 

 

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