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 :
- @openui5/sap.ui.core : this is the OpenUI5 core runtime.
It takes 26.4 MB. - @openui5/sap.m : this is the main OpenUI5 control library, with responsive controls that can be used in touch devices as well as desktop browsers.
It weighs 10.2 MB. - @openui5/themelib_sap_fiori_3 : the default theme (including specific fonts).
It requires 4.2 MB.
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:
- 1.76.0 is available under https://openui5.hana.ondemand.com/1.76.0/resources/
- 1.75.0 is available under https://openui5.hana.ondemand.com/1.75.0/resources/
- …
- 1.65.0 is available under https://openui5.hana.ondemand.com/1.65.0/resources/
- …
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.
- First you need to install Node.js
- Node.js comes with NPM but it may be updated separately using
npm install npm@latest -g
- 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) - 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.js
custom 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.