REserve — Serving an OpenUI5 application

The best way to explain what REserve can do is to demonstrate some of its features through a concrete use case. In this article, we will illustrate how one can quickly setup a server to facilitate the execution of OpenUI5 applications.

Quick presentation of OpenUI5

OpenUI5 is a free and open source JavaScript framework to develop enterprise-grade and responsive applications.

It offers some efficient development concepts, such as :

  • The Model View Controller (MVC) pattern
  • XML definition of views
  • Two-way bindings
  • Controls development with fast rendering
  • ODATA integration
  • Testing helpers (qUnit / OPA)

More information can be found in the documentation.

The community around the framework is growing and several tools are publicly available in the NPM repository.

When it comes to building an application, you must include the following NPM package to your project :

  • @ui5/cli : it contains the required UI5 tooling.
    It cumulates 27 MB of files (including dependencies).

The UI5 tooling helps the developer handle the full lifecycle of the application :

  • Initiate and configure the project (including the UI5 dependencies).
  • Serve the project locally.
  • Build a ready-to-deploy application by consolidating and minifying all the dependencies.

A minimalist application includes these dependencies :

In the end, you basically need a total of 60 MB of packages to start coding your application. Such a digital footprint is quite common for a standard Node.js development environment.

Once the application is finalized, depending on its dependencies, the deployment will live in a fraction of this size.

There is one little drawback to this model. After installing all these packages, the project is bound to the downloaded version of OpenUI5. Since a new release of OpenUI5 is done almost every month, it might be interesting to switch between versions.

However, this means cleaning the package list and install new ones.

That can be a tedious process but, good news, the version 2 of the cli tools offers a mechanism to simplify this step.

OpenUI5 Content Delivery Network

The framework is built on top of a smart dependency management model that can load the missing dependencies when needed. To put it in a nutshell, these additional modules are usually relative to the location where the OpenUI5 bootstrap is obtained.

Furthermore, each released version of OpenUI5 is available from a public CDN:

Hence, it is possible to run an application by loading the OpenUI5 resources from the CDN.

Sample application

Let’s consider a simple demonstration application that consists in one view and one button. The current version of OpenUI5 is displayed in the title as shown below. The source of the application can be found in the REserve repository.

Sample demonstration application

In the first version of the bootstrap ( static.html), the OpenUI5 framework is loaded from the CDN.

OpenUI5 is loaded from the CDN as specified in the static.html bootstrap

When opening this file directly in a browser, the application fails to load. Since scripts running via file:// have limited support for Cross-Origin Resource Sharing, it is unable to load some resources from the file system using the XMLHttpRequest object.

Loading the application from the file system fails

To work properly, the application must be served using the http protocol.

Serving with REserve

Here are the steps to build a web server using REserve.

  1. First you need to install Node.js
  2. Node.js comes with NPM but it may be updated separately using npm install npm@latest -g
  3. Install REserve globally using npm install reserve -g (it is not mandatory to make it global, but this is the fastest way to use it)
  4. Define a configuration file that describes how the incoming requests must be served (all paths are relative to the configuration file)

static.json configuration file

The above configuration contains only two mappings:

  • The first mapping intercepts requests accessing the root of the website and delivers the content of static.html thanks to the file handler.
  • The second one captures any other URL and map them directly to the file system using the substitution parameter $1 (see Capturing groups and interpolation). If the resulting path does not exist, the handler generates a 404 answer.

To start the server, simply execute reserve --config static.json.

Then, when the browser points to http://localhost:8080, the application loads properly as shown below.

The application running with REserve

In the meantime, REserve traces all the received requests (colors are available if you also install globally the colors package).

Console output of REserve

Changing the OpenUI5 version

What if we would like to test the application with a different version of OpenUI5 ? On one hand, a simple change in the static.html file would be enough. On the other hand, we could decouple the HTML bootstrap file from a given version and rely on REserve to provide this information.

In the new bootstrap file, OpenUI5 file is loaded through a relative URL (./resources/sap-ui-core.js). If you inspect the directory structure, this path does not exist.

REserve will fill the gap.

OpenUI5 is loaded through a non-existing path in the index.html bootstrap

Using HTTP redirect

One way to implement this path is to instruct the browser to get the file from a different URL when accessing the virtual one.

For instance, when /resources/sap-ui-core.js is requested, REserve answers with the HTTP 302 status code and the information to get the resource from https://openui5.hana.ondemand.com/1.76.0/resources/sap-ui-core.js.

The status handler takes care of answering the request, the new location is described in the response header.

redirect.json configuration file

When running this configuration file, the network traces of the browser show that OpenUI5 resources involve two requests :

  • The first one gets status 302 from REserve,
  • The second one gets the corresponding resource from the CDN.

The network traces show the redirect mechanism

However, only the requests served by REserve are traced, as shown below.

REserve traces showing the HTTP Status 302 answers

Changing the version dynamically

Whenever a browser connects to a server, it usually transmits additional information to give the context of the request. In particular, the Referer header contains the address of the web page accessing the resource.

Based on this standard feature, the server can be adjusted to extract an URL parameter and redirect to the expected version of OpenUI5.

The custom handler enables custom code extensions to REserve.

redirect-version.json configuration file

The custom handler simplifies the request processing by calling an asynchronous function with the Node.js’ native request and response objects. Any capturing group value is passed as additional parameters. REserve knows that the request is fully answered when the response is finalized by calling .

In the following code, the request object is used to extract the Referer header, then the version parameter is captured (if any) and the proper HTTP 302 response is built using response.writeHead.

redirect-version.js custom code

When running this new configuration file, one can now specify a version number inside the URL such as localhost:8080?version=1.65.0. This makes the application runs with the requested OpenUI5 version as demonstrated below.

The demonstration application running with version 1.65.0 of OpenUI5

As far as the traces are concerned, this does not change the output of REserve.

REserve traces showing the HTTP Status 302 answers

Content Security Policy

What happens if the website hosting the application is configured to forbid the execution of external code ? This condition is easily testable by adding a new mapping that injects a Content-Security-Policy header.

As listed below, this new mapping has no match specification. Therefore, it applies to all requests going through it. But, in the end, only the one serving the bootstrap file is relevant.

redirect-csp.json configuration file

The file csp.js, detailed below, adds the Content-Security-Policy header to tell the browser to trust only the code loaded from the website.

csp.jscustom code file

Since OpenUI5 resources are served from a CDN after the request is being redirected, it leads to an error as shown in the network traces below and the application fails to load.

The network traces show the blocked request

Consequently, the application loading is stopped and only few traces are dumped in the REserve console.

Only two requests reached REserve

Proxy

To solve this problem, the OpenUI5 resources must be served by the application website.

REserve offers an elegant solution: the url handler can forward an incoming request to any URL and tunnel the answer back to the client transparently.

Thus, the redirect mapping is replaced with a new one as shown below.

proxy-csp.json configuration file

When running this configuration file, the application is loading again despite the CSP specification. The browser network traces show that all resources are served by localhost, as illustrated below.

The application runs as if all resources are local

In the console, all the requests are completed with the status 200.

REserve appears to serve all the requests ‘locally’

A versioned proxy

Finally, to re-enable the version selection, one last configuration file is required.

As shown below, two mappings are necessary :

  • The first one defines a virtual path /@openui5/<version>/<resource> based on the url handler to map the OpenUI5 CDN.
  • The second one requires custom code to extract the expected version from the Referer header and redirect to the virtual path.

proxy-csp-version.json configuration file

The custom code is almost the same as redirect-version.js but with a different location.

proxy-version.js custom code

As expected, the application runs and the OpenUI5 version can be changed using the URL parameter version=.

The demonstration application running with version 1.65.0 of OpenUI5 served locally

Again, the console looks like the previous example.

REserve appears to serve all the requests ‘locally’

Conclusion

Not only REserve is designed to be lightweight (less than 60 kB in version 1.6.1) but it is also flexible and powerful. It solves complex problems with its specialized handlers, and it can be easily extended with custom code.

Through the article, five websites with different behaviors were setup with only few lines of configuration / code.

It enabled the use of the OpenUI5 framework without downloading 60 MB of modules. Hence if you plan to try it, it can be a fast alternative.

Passionate developer, always keen on finding new ways to do things, welcome to my thoughts.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store