CORS: Proxy server for remote OData Service in local SAPUI5 Dev

A proxy server is needed if you want to develop SAPUI5 Apps locally, e.g. in Visual Studio Code, and access a remote OData Service like Northwind OData Service. A node.js server adds CORS headers to the requests which come from a local running app.

CORS policy blocks remote OData requests
CORS policy blocks remote OData requests

A remote OData Service is added in the SAPUI5 Tutorial and causes a CORS (Cross-Origin Resource Sharing) problem if you develop the App in Visual Studio Code on your local computer. SAP does provide some information on how to solve the CORS problem, but unfortunately it did not help me, and that is the reason why I am giving some tips.

OData Service in manifest.json causes CORS problem

The OData Service which you want to use in the app is added to the manifest.json, in the SAPUI5 example the Northwind OData Service.

"dataSources": {
        "invoiceRemote": {
        "uri": "https://services.odata.org/V2/Northwind/Northwind.svc/",
        "type": "OData",
        "settings": {
          "odataVersion": "2.0"
          }
        }
      }

Unfortunately, your app is running on localhost:8080 and is not allowed to call a resource from odata.org. This is normally not a problem because the remote system would care for the CORS headers so that the browser could directly access remote URLs.

Node.js Proxy Server adds CORS headers to requests

To solve this issue you need a proxy server that adds CORS headers to the requests which come from a local running app. You can use the npm package “cors-anywhere” for example to establish a proxy server.

1. Create the file proxy.js in the same folder where your package.json is located.

2. Copy the following code into the file:

// Listen on a specific host via the HOST environment variable
var host = process.env.HOST || '0.0.0.0';
// Listen on a specific port via the PORT environment variable
var port = process.env.PORT || 8081;
 
var cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
    originWhitelist: [], // Allow all origins    
    requireHeader: ['Origin', '*'],
    removeHeaders: ['cookie', 'cookie2']
}).listen(port, host, function() {
    console.log('Running CORS Anywhere on ' + host + ':' + port);
});

3. Run the command npm install –save-dev cors-anywhere to add the package to the devDependencies of the package.json.

  "devDependencies": {
    "cors-anywhere": "^0.4.3"
  }

4. Adjust the URI of the manifest.json (add http://localhost:8081 to the beginn of https://…). Make sure that you will change the URI on the production system.

"dataSources": {
        "invoiceRemote": {
        "uri": "http://localhost:8081/https://services.odata.org/V2/Northwind/Northwind.svc/",
        "type": "OData",
        "settings": {
          "odataVersion": "2.0"
          }
        }
      }
    },

This procedure solves the CORS problem:

Node.js proxy solves the CORS problem
Node.js proxy solves the CORS problem

Different ways how to run the proxy server

Run proxy and UI5 app separately and manually

You can start the proxy manually (command: node proxy.js) before you run the command ui5 serve -o index.html for starting the app.

The disadvantage is that you have to execute two commands manually.

Run proxy and UI5 app together

As another approach you can install the npm package “npm-run-all” to start both scripts together. In this case you need to adjust the package.json:

  "scripts": {
    "start": "npm-run-all --parallel start:webapp proxy",
    "start:webapp": "ui5 serve -o index.html",
    "proxy": "node proxy.js"
  },

The command npm run start will execute both applications. Unfortunately, you have to add the proxy to each app, and this leads to my preferred way that is described next.

Run the proxy server automatically at system start

The npm package “pm2” makes it possible that the proxy server runs automatically after your OS has been booted up. This means that your proxy server is available for all of your apps.

After you installed the package (npm install -g pm2) you need to execute the following commands:

// Start the proxy
pm2 start proxy.js

// Generate an active startup script
pm2 startup

// See status of all app managed by PM2
pm2 list
npm pm2: list of managed apps
npm pm2: list of managed apps

Further information:
[1] SAPUI5: Remote OData Service
[2] Cross-Origin Resource Sharing (CORS), mozilla
[3] Proxy server: npm “cors-anywhere”
[4] Run scripts parallel with “npm-run-all”
[5] Manage apps with npm “pm2”
[6] PM2 Quickstart

Leave a Reply