HTTP Compression

Introduction

Changes in FNZ Studio 2023 LTS (patch 2023.5.1)

Appway and FNZ Studio versions before 2023 LTS (patch 2023.5.1) have HTTP compression built into the product. This feature has been removed in FNZ Studio 2023 LTS for performance and compatibility reasons. System administrators are now encouraged to enable and configure HTTP compression in the Java application server used to host FNZ Studio. For clients using the FNZ Studio Cloud, nothing has changed. HTTP compression is managed by the cloud infrastructure.

HTTP compression can significantly reduce the amount of data transferred between a web server (FNZ Studio) and a client (browser). Web resources like HTML pages, JavaScript and CSS files, and dynamic data in XML or JSON format can often be compressed by 90% or more. This improves the responsiveness of the web application as it is perceived by the user. This document explains how HTTP compression can be enabled and configured for FNZ Studio on various Java application servers.

HTTP compression is disabled by default in Java application servers. Enabling it requires some changes in the application server's main configuration file. Beside enabling the feature, system administrators can also configure different aspects of HTTP compression. The three most common parameters are:

  • Compression algorithm used by the server
  • List of compressible media types
  • Response size threshold

More details as well as our recommendation for each parameter follow in the next sections.

HTTP Compression

Compression Algorithm

There are different compression algorithms. Which algorithm will be used in a client/server communication depends on the list of algorithms supported by the two parties. The most widely used and generally available algorithm is gzip. Modern browsers and servers may also support Brotli, an algorithm developed by Google.

For HTTP compression to work, the client must tell the server which algorithms it supports. The client achieves this by including an HTTP header Accept-Encoding in every request it sends to the server. The value of this header is a comma-separated list of algorithm identifiers.

Example header submitted by most modern web browsers: Accept-Encoding: gzip, deflate, br

This tells the server that the client can decompress HTTP responses compressed with gzip, deflate, and Brotli.

The server compares this list with its own list of supported algorithms. If there are no matches, HTTP compression is not enabled for this request/response cycle. If there is exactly one match, this algorithm will be selected. If there are multiple candidates, the server may decide for one algorithm depending on its own priority list, or depending on the order in which algorithms were listed in the client's Accept-Encoding header.

For FNZ Studio, we strongly recommend enabling gzip. If supported by the server, we also recommend enabling Brotli. Since Brotli usually performs better than gzip, we suggest giving it the highest priority.

Compressible Media Types

Whether an HTTP response is compressed or not also depends on the type of content that is sent to the client. Many binary file formats like PDF, PNG or JPEG already have built-in compression. Attempting to compress an already compressed file usually only has a negative effect. It wastes CPU resources, and the double-compressed response is often even bigger than the original binary file.

HTTP compression is, therefore, only enabled if the server detects that the content to be returned has a type which is known to be compressible. This includes all text-based file formats like HTML code, JavaScript and CSS code, SVG images, but also JSON and XML data. Content types are identified by their media type.

For best performance of FNZ Studio, we recommend to enable HTTP compression for the following media types:

  • text/html
  • application/javascript and text/javascript
  • text/css
  • application/json
  • application/xml and text/xml
  • image/svg+xml
  • text/plain

If an FNZ Studio Solution deals with other text-based file formats, this list can be extended.

Response Size Threshold

Compressing an HTTP response comes with some overhead in terms of CPU usage. Relative to the size of the response, this overhead is bigger for smaller responses. It often does not make sense to try to compress very small responses. For this reason, servers usually have a threshold parameter. A typical default value is 1 or 2 KB. HTTP compression is only enabled for responses above this threshold.

For FNZ Studio, we recommend setting this threshold to 1 KB (= 1024 bytes).

Configuration

This section explains how HTTP compression can be enabled and configured in different Java application servers, using the recommended settings for FNZ Studio.

Apache Tomcat 9.0

  1. Open Tomcat's main server.xml configuration file.
  2. Depending on whether your Tomcat supports HTTP, HTTPS, or both, there may be one or two <Connector> elements.
  3. Add the following three attributes to every <Connector> element:
    • compression set to "on"
    • compressionMinSize set to "1024"
    • compressibleMimeType set to "application/javascript,application/json,application/xml,image/svg+xml,text/css,text/html,text/javascript,text/plain,text/xml"
  4. Restart Tomcat.

Example:

Copy
&lt;Connector port="8080" maxSavePostSize="2097152" URIEncoding="UTF-8"
   compression="on" compressionMinSize="1024"
   compressibleMimeType="application/javascript,application/json,application/xml,image/svg+xml,text/css,text/html,text/javascript,text/plain,text/xml"
/&gt;

More information can be found in the official Tomcat 9.0 documentation (search for "compression").

JBoss EAP 7

  1. Open JBoss' main standalone.xml configuration file.
  2. Find the <subssytem> element for Undertow: <subsystem xmlns="urn:jboss:domain:undertow:[...]">
  3. Find the <server> and then the nested <host> element for this subsystem.
  4. Add an additional <filter-ref> element: <filter-ref name="gzip-filter" predicate="regex(pattern='application/(javascript|json|xml)|image/svg\+xml|text/(css|html|javascript|plain|xml)',value=%{o,Content-Type}) and (max-content-size(value=1024) or not exists(%{o,Content-Length}))"/>
  5. Find the <filters> element for this subsystem.
  6. Add the following child element: <gzip name="gzip-filter"/>
  7. Restart JBoss.

Example (truncated):

Copy
&lt;subsystem xmlns="urn:jboss:domain:undertow:4.0"&gt;
   [...]
   &lt;server name="default-server"&gt;
      [...]
      &lt;host name="default-host" alias="localhost"&gt;
         [...]
         &lt;filter-ref name="gzip-filter" predicate="regex(pattern='application/(javascript|json|xml)|image/svg\+xml|text/(css|html|javascript|plain|xml)',value=%{o,Content-Type}) and (max-content-size(value=1024) or not exists(%{o,Content-Length}))"/&gt;
         [...]
      &lt;/host&gt;
   &lt;/server&gt;
   [...]
   &lt;filters&gt;
      [...]
      &lt;gzip name="gzip-filter"/&gt;
   &lt;/filters&gt;
   [...]
&lt;/subsystem&gt;

More information can be found in RedHat's knowledge base.

WebSphere Liberty (20.0.0.4 and higher)

  1. Open WebSphere's main server.xml configuration file.
  2. Find the <httpEndpoint> element.
  3. Add a <compression> subelement with the following settings:
Copy
&lt;compression serverPreferredAlgorithm="gzip"&gt;
   &lt;types&gt;+application/x-javascript&lt;/types&gt;
   &lt;types&gt;+application/json&lt;/types&gt;
   &lt;types&gt;+application/xml&lt;/types&gt;
   &lt;types&gt;+image/svg+xml&lt;/types&gt;
&lt;/compression&gt;
  1. Restart WebSphere.

Example:

Copy
&lt;httpEndpoint id="defaultHttpEndpoint" host="*"
              httpPort="8080" httpsPort="-1"&gt;
   &lt;compression serverPreferredAlgorithm="gzip"&gt;
      &lt;types&gt;+application/x-javascript&lt;/types&gt;
      &lt;types&gt;+application/json&lt;/types&gt;
      &lt;types&gt;+application/xml&lt;/types&gt;
      &lt;types&gt;+image/svg+xml&lt;/types&gt;
   &lt;/compression&gt;
&lt;/httpEndpoint&gt;

More information can be found in this OpenLiberty blog post and in the official OpenLiberty documentation.

Proxy Server

If there is a load balancer, web application firewall, proxy server, or another proxy-like network device running in front of your Java application server, you may also decide to enable and configure HTTP compression only on that device. The original response generated by the application server will not be compressed, but the proxy server will compress the response on-the-fly before it is sent out to the client.

The recommended configuration settings can be found in the HTTP Compression section above .

This setup should be tested carefully. It only makes sense if the proxy server is located very close to the application server and has enough CPU power to perform the compression on-the-fly.

Testing

This section describes how to test whether HTTP compression is enabled and effective.

Preparation

  1. Log in to FNZ Studio Composition (/admin/).
  2. Navigate to the Package Overview page (/admin/module/PackagesList/Base).
  3. Open the Developer Tools of your browser (F12).
  4. Switch to the Network tab.
  5. Check Disable cache.
  6. Add a column for the response header Content-Encoding.

Configuration

Testing

  1. Reload the page.
  2. Check the amount of data transferred between server and client, and the total size of all resources: Statistics

The amount of transferred data should be significantly smaller than the size of all resources. 3. The column Content-Encoding contains the identifier of the algorithm used to compress the response. * If it is empty, the response has not been compressed. * The column should show gzip"(or br if Brotli is used) for all HTML, JavaScript, and CSS resources, as well as for SVG images, and XML and JSON data, unless their size is below 1 KB. * Binary files like PNG images or WOFF font files must not have been compressed. Responses

  1. If there are any discrepancies to the expected behavior described here, carefully review the configuration of your application server.