The Response Body Injection (RBI) module provides a filter that allows you to manipulate an HTML document received in an HTTP response from a backend server.

It can insert content into any of the following HTML elements:

  • html

  • head

  • title

  • body

Install the RBI module

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

    apt install hapee-1.7r2-lb-htmldom

    or

    yum install hapee-1.7r2-lb-htmldom
  2. In the global section of your HAProxy configuration file, add the following line:

    module-load hapee-lb-htmldom.so

Configure the RBI module

  • Add a filter htmldom directive to a listen, frontend, or backend section to begin injecting content.

    The following example replaces HTTP with HTTPS.

    Add this line to a frontend to replace HTTP links with HTTPS links. This occurs in JavaScript as this module isn't yet capable of arbitrarily modifying body contents. You can also modify it to change domain names or similar:

    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>'

    It injects the following markup into the head of the HTML document, which replaces http:// with https:// in links:

    <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>

When RBI automatically opts out

The RBI filter automatically deactivates under certain conditions. These are conditions when:

  • 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 contains compressed content (i.e. the Content-Encoding header is present)

  • The response contains the no-transform value in the Cache-Control header (no transformations or conversions can happen)

  • the Content-Type header value is other than text/html

How RBI modifies responses

The filter also modifies the response in the following ways:

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

  • In order to modify the response, the filter removes all occurrences of the Content-Length header. If the message is HTTP/1.1 or above, it sets the Transfer-Encoding header is set to chunked.

Note

When you insert a large amount of content into a response, it is important to set tune.bufsize to the appropriate size.

Filter parameters

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

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.

Precautions and troubleshooting

  • 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 (such as compression filter).

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