HAProxy Enterprise Documentation 2.3r1

Response Body Injection

The Response Body Injection (RBI) module allows you to insert content into an HTTP response before it is sent back to the client. It can insert content into any of the following HTML sections:

  • <html>

  • <head>

  • <title>

  • <body>

Install the RBI module

  1. Install the RBI module as follows, depending on your platform:

    $ # On Debian/Ubuntu
    $ sudo apt-get install hapee-2.3r1-lb-htmldom
    $ # On CentOS/RedHat/Oracle/Photon OS
    $ sudo yum install hapee-2.3r1-lb-htmldom
    $ # On SUSE
    $ sudo zypper install hapee-2.3r1-lb-htmldom
    $ # On FreeBSD
    $ sudo pkg install hapee-2.3r1-lb-htmldom
  2. In the global section of your HAProxy Enterprise configuration file, add a module-load line:

    global
       module-load hapee-lb-htmldom.so
  3. Add a filter htmldom directive to a listen, frontend, or backend section to begin injecting content.

    In this example configuration, we replace all http:// links in the page with https:// by injecting a Javascript <script> tag inside the <head> section.

    The script does the work of updating the links on the page.

    frontend www
        filter htmldom mode strict head-append '<script type="text/javascript" defer="defer">window.addEventListener("load", function() {var alinks = document.getElementsByTagName("a");var acount = alinks.length;for (var i=0; i < acount; i++) {alinks[i].href = alinks[i].href.replace("http://","https://");}})</script>'

    A closer examination of the script will give you more details about how it works.

    <script type="text/javascript" defer="defer">
        window.addEventListener("load", function() {
            var alinks = document.getElementsByTagName("a");
            var acount = alinks.length;
    
            for (var i=0; i < acount; i++) {
                alinks[i].href = alinks[i].href.replace("http://","https://");
            }
        })
    </script>

Caveats

The RBI filter automatically deactivates under certain conditions, including:

  • the request method is HEAD;

  • both request and response are HTTP/1.1, but the Transfer-Encoding header value is not chunked and Content-Length is unknown;

  • the response is compressed (i.e. the Content-Encoding header is present);

  • the response contains the Cache-Control header set to no-transform (no transformations or conversions can happen);

  • the Content-Type header is set to a value other than text/html;

Also, note that:

  • you can only use one htmldom filter per listener/frontend/backend.

  • due to the current limitation of the filter's implementation, we do not recommended that you use this filter in combination with other filters that modify the response on the same listener/frontend/backend. Using them can cause undefined behavior (for example, the compression filter).

  • if you encounter problems with the response body manipulation, check your HAProxy Enterprise logs. The RBI filter logs problems related to the buffer operations, such as initialization and manipulation.

Changed HTTP headers

The filter htmldom directive modifies the response in the following ways:

  • It removes all occurrences of the Accept-Encoding header from the incoming request to ensure that the response does not get compressed.

  • It removes all occurrences of the Content-Length header in order to modify the response.

  • If the message is HTTP/1.1 or above, it sets the Transfer-Encoding header to chunked.

Filter parameters

The filter htmldom directive instructs HAProxy Enterprise to inject content into an HTML document. You can declare it only once for each proxy section. Its syntax is:

# Used in the a frontend, listen, or backend section
     filter htmldom [mode <mode>] <action> <content>

where:

Directive

Description

mode <mode>

Sets the HTML parser in either of these modes:

relaxed (default)

Faster and intended for use cases where you know what to expect in the server response (the HTML document is simple).

strict

Uses libxml2 and performs more parsing checks. We recommend this in cases where the document may contain many JavaScript declarations or if there may be broken tags.

<action> (required)

Identifies the HTML element in which to inject new content. It applies to the first matching element. Valid actions are:

html-prepend

Insert content at the beginning of the <html> element.

html-append

Insert content at the end of the <html> element.

head-prepend

Insert content at the beginning of the <head> element.

head-append

Insert content at the end of the <head> element.

title-prepend

Insert content at the beginning of the <title> element.

title-append

Insert content at the end of the <title> element.

body-prepend

Insert content at the beginning of the <body> element.

body-append

Insert content at the end of the <body> element.

<content> (required)

The HTML content to inject into the response from a server. It is a log-format string.


Next up

Session Persistence