Product Information
Migration from XS classic – Making http/https external outbound calls using xsjs and xsodata in XSA
This blog is written due to the issues faced while implementing xsjs and xsodata together with XS advanced MTA application while migration of XS classic applications to XS Advanced in a side car scenario. This is an advanced blog so for initial setup and usage of any external http service in XSA please follow the below tutorial first.
https://developers.sap.com/tutorials/xsa-xsjs-access-external-service.html
The need: whenever you will be migrating from xs classic to xs advanced you will faces issues of making outbound calls from xs advanced server to a different server in case your XS classic application talks to multiple servers basically if you are calling a MDG box via odata or S4 Box via a odata and you have a centralized hub architecture. All the XS classic implementation involving xsodata includes hosting the ui5 application on a centralized gateway and hence you do not need to call any external server from your application as all services are hosted on a Gateway Server and the ui5 application component is also hosted on the same server but when you migrate your ui5 component to the new XSA architecture and create a multi target application then these points need to be considered.
The prerequisite that need to be considered :
- The HANA instance making an external outbound call needs to have all appropriate certificates that need to be downloaded now in your XSA HANA instance.
- useSSL = true in .xshttpdest file
- While making an external outbound call the xscrf token must be handled properly.
The XS classic application using xsodata creates an odata model for usage and the metadata call is handled by the framework and it fetches the token for you which you can send in a post call by calling omodel.create(). When you migrate to XS advanced and create an mta application the calls are routed through a hana server to an external server. Hence the token that is fetched by the odata call is not understood during the post call. We have to explicitly get the token from the external server and then do a POST call like below:
if ($.request.method === $.net.http.POST) {
var client = new $.net.http.Client();
var req = new $.web.WebRequest($.net.http.HEAD, ‘/sap/opu/odata/sap/ZHVC_RISK_SWB_SRV/$metadata’);
req.headers.set(“x-csrf-token”, “fetch”);
req.headers.set(“Connection”, “keep-alive”);
req.headers.set(“X-Requested-With”, “XMLHttpRequest”);
client.request(req, destination);
var response = client.getResponse();
var CSRF = response.headers.get(“x-csrf-token”);
var request = new $.net.http.Request($.net.http.POST, “/sap/opu/odata/sap/ZHVC_RISK_SWB_SRV/EtDataSet”);
request.headers.set(“x-csrf-token”, CSRF);
request.headers.set(“X-Requested-With”, “XMLHttpRequest”);
request.headers.set(“Content-Type”, “application/json”);
request.headers.set(“Accept”, “application/json”);
var ui5body = $.request.body.asString();
request.setBody(ui5body);
try {
client.request(request, destination);
var newresponse = client.getResponse();
var myBody;
if (newresponse.body) { myBody = newresponse.body.asString();
}
} catch (e) {
myBody = response.body.asString();
}
$.response.contentType = newresponse.contentType;
$.response.setBody(myBody);
Frequent Errors that you might get:
- If the body is not passed as string you might get invalid argument error and the node.js server will crash
- Econnreset error , if you are making https calls and do not add useSSL = true in xshttpdest file
- If you already have done a GET call and you pass the csrf token obtained into response headers and then again try to do a POST call explicitly with a new token you will get csrf token validation failed. The framework doesn’t identify the token that you might pass via AJAX calls like this:
=> if ($.request.method === $.net.http.GET) {
// your get call and passing of the token
var request = new $.net.http.Request($.net.http.GET, “url”
request.headers.set(“x-csrf-token”, “fetch”);
try {
var response = client.request(request, destination).getResponse();
myBody = response.body.asString();
}
$.response.headers = response.headers;
$.response.contentType = response.contentType;
$.response.setBody(myBody);
else if ($.request.method === $.net.http.POST){
// your post call logic of passing the token from the get call
}
If you make an AJAX call in your code with the above token that you will get from the response headers of the previous(GET) request and make a post call again then also you will face the csrf token validation error. Hence both the calls to fetch the token and passing into the POST call have to be made in a single http method call via the ui5 code.
Hope this helps and i will try to add more blogs on XS Classic migration when the whole database is migrated and consumed via user provided service in your new containerized MTA application. Basically the synonyms along with sql. modification exits and xsjslib exits are used for CRUD operations. will talk more in the next blog.