Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
joachimvanpraet
Active Participant
Hi all,

There are a lot of http clients available to consume HTTP service in Javascript.
There are a lot of discussions on which one is the best, I love them all, but in the end you have to use only one.

My personal favorite is axios. it's well documented, supports many features and is easy to learn.
That's why I decided to make the life of the axios users in the SAP Cloud Foundry easier and created a sap-cf-axios library.

Let's start with explaining all different parts we need to make an http call.

Destinations


Destinations are defined in the cloud cockpit.
We use these destinations to configure our connection:

  • a base url

  • authentication configuration

  • proxy configuration


Using the destination in a nodejs applications requires a binding to a destination service. If the destination is pointing to an on premise system we have to connect to this service via the cloud connector. To call a service over the cloud connector we have to adapt our proxy settings in our http client. To read the configuration of the proxy and the authentication information, we need to bind our application to a connectivity service.

In my example here I define 3 services (UAA, destination and connectivity) and I bind the services to my approuter and service.
ID: sap-cf-axios-example
_schema-version: "2.1"
description: Example sap cf axios
version: 0.0.1
modules:
- name: sca_approuter
type: approuter.nodejs
path: approuter
parameters:
disk-quota: 256M
memory: 256M
requires:
- name: sca_uaa
- name: sca_destination_service
- name: sca_api
group: destinations
properties:
forwardAuthToken: true
name: sca_api
strictSSL: false
url: '~{url}'
- name: sca_srv
type: nodejs
path: srv
parameters:
memory: 512M
disk-quota: 256M
provides:
- name: sca_api
properties:
url: ${default-url}
requires:
- name: sca_uaa
- name: sca_connectivity_service
- name: sca_destination_service
resources:
- name: sca_destination_service
type: destination
parameters:
service-plan: lite
shared: true
- name: sca_connectivity_service
type: connectivity
parameters:
service-plan: lite
shared: true
- name: sca_uaa
type: com.sap.xs.uaa
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json

Axios


https://github.com/axios/axios

When we use axios in nodejs we have to create an AxiosRequestConfig object that specifies the properties like method, url, payload, headers of the call we need to send to our service.

The return of the axios function is a promise with the AxiosResponse object where we can read the response header and the body among other things. Let's give an example of an odata service served on https://my.site/myService.

If we want to post a Book entity to this service that requires authentication we can use this code:
const axios = require('axios');

const response = await axios({
method: "post",
url: "/BookSet",
baseUrl: "https://localhost:3002"
data: {
title: "Using Axios in SAP Cloud Foundry",
author: "Joachim Van Praet"
},
headers: {
"content-type": "application/json"
},
auth: {
username: 'jowa',
password: 's00pers3cret'
}
})

Axios with destinations


To use axios with the destination and connectivity service you can install the sap-cf-axios in your application.
npm install -s sap-cf-axios

To keep the use of axios as close as possible to the standard. I decided to create an axios instance for each destination. For each destination a request interceptor will override the data in the AxiosRequestConfig object with the configuration in the destination before starting the request.

Let's take the same example as before. Let's post a new Book to the service.
const {SapCfAxios} = require('sap-cf-axios');
const destinationName = "MyDestinationNameInCloudFoundry";
const axios = SapCfAxios(destinationName);

const response = await axios({
method: "post",
url: "/BookSet",
data: {
title: "Using Axios in SAP Cloud Foundry",
author: "Joachim Van Praet"
},
headers: {
"content-type": "application/json"
}
})

As you can see we deleted the baseUrl and auth property from our call. These properties will be read from the destination and injected by the sap-cf-axios library. If it is an onpremise service the proxy settings will also be injected by the library.

Use it yourself


Let's try this thing!

I created a nodejs service to run locally. You can find it in here: https://github.com/jowavp/show-request

just run:
npm install
npm run start

The service starts on port 3002. The response of the service is a representation of the request parameters that are sent to this service.

let's try it with postman locally. This is the request:
POST /BookSet HTTP/1.1
Host: localhost:3002
Content-Type: application/json
Authorization: Basic am93YTpzMDBwZXJzM2NyZXQ=
User-Agent: PostmanRuntime/7.19.0
Accept: */*
Cache-Control: no-cache
Postman-Token: ab328757-526e-4ab3-9464-d454a9abd9a1,157664fa-0efa-41ea-a97a-f440e836eb81
Host: localhost:3002
Accept-Encoding: gzip, deflate
Content-Length: 89
Connection: keep-alive
cache-control: no-cache

{
"title": "Using Axios in SAP Cloud Foundry",
"author": "Joachim Van Praet"
}

The response of this request is the following:
{
"method": "POST",
"baseUrl": "",
"uri": "/BookSet",
"host": "localhost",
"headers": {
"content-type": "application/json",
"authorization": "Basic am93YTpzMDBwZXJzM2NyZXQ=",
"user-agent": "PostmanRuntime/7.19.0",
"accept": "*/*",
"cache-control": "no-cache",
"postman-token": "ab328757-526e-4ab3-9464-d454a9abd9a1",
"host": "localhost:3002",
"accept-encoding": "gzip, deflate",
"content-length": "89",
"connection": "keep-alive"
},
"body": {
"title": "Using Axios in SAP Cloud Foundry",
"author": "Joachim Van Praet"
}
}

nothing fancy here because there is nothing happening with our request. It is send from postman to the service, so what we put in postman we will see in the response of our service. But things will get interesting when we use sap-cf-axios in cloud foundry to call our local service. First we have to configure the service in cloud connector so we can access it in cloud foundry.



Then we define a destination in cloud foundry that points to our local service using it's virtual hostname.



When this configuration is done. We deploy a simple nodejs service that will call this destination with sap-cf-axios. https://github.com/jowavp/sap-cf-axios-example
const express = require('express');
const app = express();
const {SapCfAxios} = require('sap-cf-axios');
// the destination that we want to use is named 'DUMMY'
const axios = SapCfAxios('DUMMY');

app.use(express.json());

const handleRequest = async (req, res) => {
try {

const response = await axios({
method: 'POST',
url: '/BookSet',
data: {
title: "Using Axios in SAP Cloud Foundry",
author: "Joachim Van Praet"
},
headers: {
"content-type": "application/json"
/* if you are using an oauth2* authentication type or principal propagation
* for your destination
* please add your JWT token in the authorization header of this request
**/
// authorization: <user JWT Token>

}
});
res.send(response.data);
} catch (error) {
res.reject(error);
}
}

app.all('*', handleRequest);

const port = process.env.PORT || 3000;;
app.listen(port, function () {
console.log('myapp listening on port ' + port);
});

you can deploy this application by running: (you need cli & mbt installed)
npm install
npm run build
npm run deploy

Once this application is deployed, we can open the url of the approuter to test it.



When we now look to the response. we see:
{
"method": "POST",
"baseUrl": "",
"uri": "/BookSet",
"host": "localhost",
"headers": {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"authorization": "Basic am9hY2hpbTpzMDBwZXJzM2NyZXQ=",
"sap-connectivity-scc-location_id": "my_cloud_connector_location_id",
"user-agent": "axios/0.19.0",
"content-length": "73",
"connection": "close",
"host": "localhost:3002",
"x-forwarded-host": "dummy:3000"
},
"body": {
"title": "Using Axios in SAP Cloud Foundry",
"author": "Joachim Van Praet"
}
}

As you can see sap-cf-axios added the authorization header and handled the proxy configuration to call the service on our local environment.

So, I hope this sap-cf-axios will make your life easier in consuming destinations in SAP cloud foundry. There are still some features missing that I will add when I need them. 🙂

 

kr,

Joachim

 
36 Comments
Labels in this area