Node.js – Invoking Secured REST Services in Fusion Cloud – Part 1

March 26, 2015 | 6 minute read
Text Size 100%:

Introduction

This post focuses on invoking secured Fusion Cloud RESTFul services using Node.js. Part 1 is explicitly focused on the "GET" method. The assumption is that the reader has some basic knowledge on Node.js. Please refer to this link to download and install Node.js in your environment.

Node.js is a programming platform that allows you to execute server-side code that is similar to JavaScript in the browser. It enables real-time, two-way connections in web applications with push capability, allowing a non-blocking, event-driven I/O paradigm. It runs on a single threaded event loop and leverages asynchronous calls for various operations such as I/O. This is an evolution from stateless-web based on the stateless request-response paradigm. For example, when a request is sent to invoke a service such as REST or a database query, Node.js will continue serving the new requests. When a response comes back, it will jump back to the respective requestor. Node.js is lightweight and provides a high level of concurrency. However, it is not suitable for CPU intensive operations as it is single threaded.

Node.js is built on an event-driven, asynchronous model. The in-coming requests are non-blocking. Each request is passed off to an asynchronous callback handler. This frees up the main thread to respond to more requests.

 

Main Article

An internet media type data for RESTFul services is often JavaScript Object Notation (JSON). JSON is a lightweight data-interchange format and it is a standard way to exchange data with RESTFul services. It is not only human readable, but easy for machines to parse and generate. For more information on JSON, please refer to this link.

JSON Samples:

Simple Data Structure
Var Employee = { “name” : “Joe Smith” “ID” : “1234” “email” : joe.smith@oracle.com };
Data in Arrays
var emailGroups = [{ "email" : "email1@myCompany.com", "name" : "Joe Smith" }, { "email" : " email2@myCompany.com ", "name" : "Don Smith" }];

 

Security

The RESTFul services in Oracle Fusion Cloud are protected with Oracle Web Service Manager (OWSM). The server policy allows the following client authentication types:

  • HTTP Basic Authentication over Secure Socket Layer (SSL)
  • Oracle Access Manager(OAM) Token-service
  • Simple and Protected GSS-API Negotiate Mechanism (SPNEGO)
  • SAML token

The client must provide one of the above policies in the security headers of the invocation call for authentication. The sample in this post is using HTTP Basic Authentication over SSL policy.

 

Node.js HTTP Get Request

In general there are two modules to invoke HTTP/s secured REST services for GET method:

  • 1. http.get() - This is a native HTTP/s API and supports only GET method.
  • 2. http.request() - The request is designed to make HTTP/s calls and supports multiple request methods such as GET, POST, PUT, DELETE, etc.

HTTP GET Module

This native API implicitly calls http.request set to GET and calls request.end() automatically. There are two parameters for this method that defines what and how the REST services is being invoked. The following snippet demonstrates the construct for HTTP/s invocation:

var client = require('https') request = client.get(options, function(response) {…}

The above command uses HTTPS protocol. The “require” statement enables either HTTP or HTTPS protocol.

Options

The "options" is an object or string that includes the following information:

  • host -  A domain name or IP address of the server to issue the request to.
  • port - Port of remote server.
  • Path - Uniform Resource Idenitifier (URI)
  • HTTP Headers - HTTP headers that must be sent with the request such as authorization
  • Certificates - certificates such as ca cert for SSL

For more information on object "options", refer the following link.

This a typical example of constructing 'option'

var options = { ca: fs.readFileSync('myCert'), host: 'hostname.mycompany.com', port: 443, path: '/hcmCoreApi/atomservlet/employee/newhire', headers: { 'Authorization': 'Basic ' + new Buffer(uname + ':' + pword).toString('base64') }

 

function(response)

This is a callback parameter as a one time listener for the response event. It is emitted when a response is received to this request.

To get the response, add a listener for 'response' to the request object. The 'response' will be emitted from the request object when the response headers have been received. The 'response' event is executed with one argument which is an instance of http.IncomingMessage.

During the 'response' event, one can add listeners to the response object; particularly to listen for the 'data' event.

If no 'response' handler is added, then the response will be entirely discarded. However, if you add a 'response' event handler, then you must consume the data from the response object, either by calling response.read() whenever there is a 'readable' event, or by adding a 'data' handler, or by calling the .resume() method. Until the data is consumed, the 'end' event will not fire. Also, until the data is read it will consume memory that can eventually lead to a 'process out of memory' error.

Note: Node does not check whether Content-Length and the length of the body which has been transmitted are equal or not.

The following sample has implemented three events:

  1. 1. Data - an event to get the data
  2. 2. End - an event to know the response is completed.
  3. 3. Error - an event to capture the error and trigger your error logic handler.
request = http.get(options, function(res){ var body = ""; res.on('data', function(chunk) { body += chunk; }); res.on('end', function() { console.log(body); }) res.on('error', function(e) { console.log("Got error: " + e.message); }); }); 

 

HTTP Request Module

The request module is designed to make various HTTP/s calls such as GET, POST, PUT, DELETE, etc. The http.get() implicitly calls http.request set to GET and calls request.end() automatically. The code for GET method is identical to http.get() except for the following:

  • The http.get() is replaced with “http.request()”
  • The "option" object has a method property that defines the HTTP operation (default is GET)
  • The request.end() is explicitly called to signify the end of the request
Sample Snippet:
var options = { ca: fs.readFileSync('myCert'), host: 'hostname.mycompany.com', port: 443, method: GET, path: '/<fusion_apps_api>/employee', headers: { 'Authorization': 'Basic ' + new Buffer(uname + ':' + pword).toString('base64') } var request = http.request(options, function(res){…} …. request.end();

 

Response Status Codes and Headers

The HTTP status code is available from response event function function(res). For example

res.statusCode

 

The HTTP response headers are available from same response event function as follows:

res.headers

 

Parsing JSON Response

The response JSON message can be parsed using JSON object. The JSON.parse() parses a string from the RESTFul services. For example:

JSON.parse(responseString)

 

Sample Code got http.get()

var uname = 'username'; var pword = 'password'; var http = require('https'), fs = require('fs'); var options = { ca: fs.readFileSync('MyCert'), host: 'host.mycompany.com', port: 10620, path: '/<fusion_apps_api>/employee', headers: { 'Authorization': 'Basic ' + new Buffer(uname + ':' + pword).toString('base64') } }; request = http.get(options, function(res){ var responseString = ""; res.on('data', function(data) {
responseString += data;
}); res.on('end', function() { console.log(responseString);
}) res.on('error', function(e) { console.log("Got error: " + e.message); }); });

Sample Code for http.request()

var uname = 'username'; var pword = 'password'; var http = require('https'),     fs = require('fs'); var options = {     ca: fs.readFileSync('hcmcert1'),     host: 'host.mycompany.com',     port: 10620,     path: '/<fusion_apps_api>/employee',     method: 'GET',     headers: {      'Authorization': 'Basic ' + new Buffer(uname + ':' + pword).toString('base64')    } }; var    request = http.request(options, function(res){     console.log(res.headers);     var responseString = '';     res.on('data', function(chunk) {          console.log(chunk);          responseString += chunk;     });     res.on('end', function() {         console.log(responseString);     })     res.on('error', function(e) {         console.log("Got error: " + e.message);     }); }); request.end();

Conclusion

This post demonstrates how to invoke secured Fusion Cloud REST Services using Node.js. It also provides basic introduction to JSON format and how to parse the JSON response in Node.js. The sample code is a prototype and must be further modularized for re-usability.

 

Jack Desai

A product strategist and “solution and enterprise” integration architect to innovate and automate complex integration patterns with Oracle SaaS applications.


Previous Post

Fusion HCM Cloud Bulk Integration Automation

Jack Desai | 10 min read

Next Post


Getting Groovy with Oracle Data Integrator: Automating Changes after Upgrading ODI or Migrating from Oracle Warehouse Builder

Christophe Dupupet | 10 min read