Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
This blog is part of a series of tutorials explaining the usage of SAP Cloud Platform Backend service in detail.

Quicklinks:
Code


You can use Backend service to easily creat…..
Oh, no, thanks, I have enough APIs, guess I’ll search for another tutorial seri…
Hey, stop, just tell what you’re looking for
Guidance how to write node.js app to call APIs from exter...
But that’s what I was about to to say...
Ah, cool, just say

Assuming you have created enough APIs in the Backend service cockpit
Assuming you have learned how to access and test your APIs from external REST client
Maybe now you wish to take a next step and programmatically call the API from outside the cloud.
Could be necessary e.g. for automatically testing your APIS with local test script.
Such script might be running in a Jenkins build server, whatever.
And I wish example code
A wish which I fully understand
And also I wish to support such wish.
So here it comes:
Example node.js code to call Backend service API

Note:
I think that you should be able to follow this blog, even if you’re completely new to node.js

Prerequisites


Although in this tutorial we just write a small basic node.js application, there are quite a few prerequisites and configuration steps to be done.

Cloud:
You’ve created an API in Backend service. (see here)
You’ve gone through the description of manually calling API from REST client tool
In order to achieve that, there’s a prerequisite: configure security in Cloud account
You might also go through the OAuth 2 blog to understand a bit more about the background

node.js:
You might want to have a look at this section, where I’ve already described the necessary steps to be prepared to run node
Note:
In this present blog, no SAP-specific node modules are required, so you don’t need to configure the npm registry

Prepare it


Before writing the code, it makes sense to collect some user-specific data to be entered later:

Backend service API

You need the URL of the OData service which you want to call.
Important to mention:
To view the URL, we usually open the URL in the cockpit of Backend service.
But this URL is not really the one which we can use to call it externally.
So we need to slightly modify the URL:
It has to be prefixed with backend-service-api instead of
<yourSubaccount>-backend-service
See my example below

Cloud environment

Assuming, you have prepared your cloud account with creating a service instance of xsuaa and creating a service key
Now you can go there and take a note of the required properties
Furthermore, take a note of your OData service which you want to call, i.e. the API created on Backend service

These are my example values:




























API https://backend-service-api.<...>/odatav2/DEFAULT/PRODUCTSERVICE;v=1/Products
clientid

sb-xsuaaName!t12345

secret

VZz5this37dJ6eTVmightbeKhfGf56lw=

Uri https://<subaccount>.authentication.eu10.hana.ondemand.com/oauth/token
user myDummyUser@myMail.com
pwd theUsual123


Local environment

Prepare your local environment for node.js development:
Experienced users may skip this section

All we need is a dedicated folder
Create a folder
e.g. C:\tmp_bsnode
Open command shell and navigate to that folder



Now we can install the required dependencies.
Run the following command:







npm install client-oauth2


like here:



This command installs a node module which helps us dealing with the OAuth2 flow
Similarly execute the following 2 commands







npm install request


and







npm install request-promise


Result:
In our file system, the folder node_modules has been created in our working directory.
It contains all required dependencies



Note:
I think it is easier for the moment to live without package.json file
Reason is that it isn't possible to attach files or archives to the blog.
So I think it is easier to follow the blog, if there's only one file

Code it


Now it is time for our application code.
Inside our working folder, we create a javascript file
e.g. app.js



Note:
Before you go ahead:
The next step is to paste the code and afterwards to run it BUT:
BUT there’s a BUT:
Don’t forget it:
B U T before running the app, you need to read a NOTE.
Don’t forget it
Otherwise it won’t work.
And you’ll complain.
BUT: I’ve warned you early enough

OK
OK, open the file with an editor of your choice, e.g. Notepad

Note:
A good choice is Visual Studio Code
Yes, I installed it when following the CDS modelling blog
Fantastic

Paste the following code:



'use strict';

const oauthClient = require('client-oauth2');
const request = require('request-promise');

// OData service, created in Backend service
const SERVICE_URL = 'https://backend-service-api.cfapps.eu10.hana.ondemand.com/odatav2/DEFAULT/PRODUCTSERVICE;v=1/Products';

// helper method which uses client-oauth2 library to get access token from XSUAA
const _getAccessToken = function() {
return new Promise((resolve, reject) => {
const oautClient = new oauthClient({
accessTokenUri: 'https://bssubaccount.authentication.eu10.hana.ondemand.com/oauth/token',
clientId: 'sb-XsuaaForAuthCode!t13020',
clientSecret: 'VZz539437dJ6eTVmigKhfGG89lw=',
scopes: []
});

oautClient.owner.getToken('yourUser@yourMail.com', 'theUsual123')
.then(result => {
resolve({accessToken: result.accessToken});
})
.catch(error => {
reject({message: 'Error: failed to get access token.', error: error});
});
});
}

// helper method for calling Backend service API, using the previously fetched token
const _doQUERY = function (serviceUrl, accessToken){
return new Promise (function(resolve, reject){
const options = {
url: serviceUrl,
resolveWithFullResponse: true ,
headers: {
Authorization: 'Bearer ' + accessToken,
Accept : 'application/json'
}
};

request(options)
.then(response => {
if(response && response.statusCode == 200){
resolve({responseBody: response.body});
}
reject({ message: 'Error while calling OData service'});
})
.catch(error => {
reject({ message: 'Error occurred while calling OData service', error: error });
});
});
};

// The script calling Backend service API
console.log('Calling Backend service-API ...');
_getAccessToken()
.then(result => {
console.log('Successfully fetched OAuth access token: ' + result.accessToken.substring(0,16));
return _doQUERY(SERVICE_URL, result.accessToken);
})
.then(result => {
console.log('Successfully called OData service. Response body: ' + result.responseBody.substring(0,111));
// do anything like: JSON.parse(result.responseBody).d.results;
})
.catch(error => {
console.log(error.message + ' Reason: ' + error.error);
});

Node:
Now it comes, the node...
What?

Note:
Sorry, a typo, I don’t mean a node, I mean a note

The Note:
You have to change the code:
Make sure to enter your personal data, which you prepared in the preparation section above
Line 7: Enter the URL of your personal Backend service API, it should be a collection
Line 13: Enter the URL which comes from your xsuaa instance, it should end with /oauth/token
Line 14: Enter the clientid of your xsuaa instance
Line 15: Enter the clientsecret of your xsuaa instance
Line 19: Enter your personal cloud user
Line 19: Enter the password of your personal cloud user

Note:
That’s it, now you can run it

Run it


To run the node.js application, change to your command prompt and make sure you’re in the same working directory as usual
Type the following command and press enter







node app.js


As a result, the application is executed.
It prints a few success messages.
What success, what messages?
No?
It prints an error message: Error: failed to get access token ???
I cannot believe it....Did you read my note…
Which note?
aaaaarghhh...
See here how to adapt the sample code:



OK
After adapting the code to your personal data, you’ll get the 2 success messages.
Hopefully…



Note:
The following section explains a little bit what we’ve been doing

Understand it


Note:
First of all, my apologies for the code which probably could be better, but I’m not a pro and I’ve tried to keep it short
Yes, it looks awful
OK
What is done in that ugly code?

The application does 2 things
1. use the node module client-oauth2 to do the OAuth 2 flow in order to get the access token
2. use the node module request-promise to call  the OData service (with token)

Both are encapsulated in helper methods (line 10 and line 29)
Both helper methods are called subsequently (with Promises), starting in the “Script” section at line 54

Note:
For calling OData services, there are other node packages, but today I wanted to be simple.

What is interesting in the code?
We use the “Resource Owner Password Credentials” grant type of OAuth 2, therefore we use the “owner” to fetch the token.
oautClient.owner.getToken('user', 'pwd')

Like that, it is quite easy to get the required token
Once we have it, we use it as header in the request which we send to the OData service:
Authorization: 'Bearer ' + accessToken,

We're also setting another header:
Accept : 'application/json'

This is done to ensure that the OData service sends its response payload in JSON format.
Like that, it is easy to process further

However, today we don’t process it further…
Oh, already the end?
Yes,but I'll be back
Hasta la vista Baby

Troubleshooting


What to do if you happily deploy everything and try testing and get..... Forbidden ???
See this blog for a Troubleshooting guide

Summary


In this blog we've learned how to call a Backend service API from an external node application.
Honestly, there's nothing special in this blog.
We've

used 2 standard node modules to do 2 standard calls:
Get OAuth token
Call OData service

However, I believe it is always good to have sample code, to be ready to easily use Backend service:
With SAP Cloud Platform Backend service you can easily create APIs and with the help of this blog you can easily consume it with external node.js application

You've made it

Glad that I've finally concluded my sentence

Advertisements


Little node.js tutorial series:
Call API from external node application: this blog
Call API from node app, deployed to Cloud Foundry, everything done manually
Call API from node app inside CF using XSUAA service binding
Call API from node app inside CF using XSUAA login screen
Call API from node app inside CF using Destination service binding

Call API from external app, means local REST client

Preparation info:
Configure xsuaa for usage from external app/tool
Configure BETA subaccount to enable xsuaa configuration
OAuth intro:
Explaining OAuth 2 mechanism for Backend service, security mechanism
Explaining OAuth "Authorization Code" grant type, also supported by Backend service

All Blogs and tutorials: overview of blog series

Links


https://nodejs.org/en/

client-oauth2

request-promise

 
9 Comments