LTM's built-in stream profile (and related iRules commands) offer a relatively low-overhead method to replace specific strings in the server response data. 

One of the most common uses for stream replacement is to re-write server-referencing links in HTTP payload -- re-write to https when using SSL acceleration, re-write the hostname to the virtual server hostname, or rewrite the the URI to match a customer-facing scheme.  But what if you need to replace multiple strings with the same replacement text, or replace more than one string with the same string (i.e. rewrite URI's for 2 different paths names in the same response)?

Since only one stream operation can be performed on any given response, you might assume it can't be done with the stream profile.  Not so: The stream profile parameters can be configured so a single stream operation will perform multiple replacements against the same data, or to use basic regular expressions to find the strings you need to replace.

Multiple stream replacements using the stream profile
To replace multiple strings in server-returned content using the stream replacement feature, start by creating a custom Stream profile (Local Traffic / Profiles / Other / Stream).   Leave the "Source" field blank.  In the "Target" field, enter each string you'd like to replace followed by the replacement text  in the following format:
 
<d><search1><d><replace1><d><d><search2><d><replace2><d>...

The first character in the field (<d>) defines the delimiter bounding each field for this replacement, and must not appear anywhere else in the target string.  <d> can be any one of the following characters:

.*/-:_?=@,&
    (period, asterisk, forward slash, dash, colon, underscore, question mark, equals, at, comma, ampersand)

So to replace all instances of "string1" with "string2", and all instances of "string3" with "string4", you could use this syntax for the Target field:
 
/<string1>/<string2>/ /<string3>/<string4>/

Multiple stream replacements using an iRule

To perform multiple search & replace operations with an iRule instead of the stream profile settings (very useful if different conditions dictate different replacements), use the same syntax with the STREAM::expression command:

when HTTP_RESPONSE {
     if {[HTTP::status] ==200}{
       STREAM::enable
       STREAM::expression \
            "@A phrase;@is replaced by this phrase:@ @something else@être remplacé par pourtant une plus longue corde des textes dans une autre langue@"
     }
   }


Using regular expressions for stream replacement
Regular expressions (basic regex ONLY) are supported in the search string portion of the Target parameter. Here's an example that looks for patterns matching IP addresses and replaces each one with 0.0.0.0 :

@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}@0.0.0.0@

To use this approach in an iRule, you'll need to enclose the Target string in { } instead of " " when defining the STREAM::expression parameter:

STREAM::expression {@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}@0.0.0.0@}

(Thanks to hoolio for this example.)

You can also combine regular expressions and multiple searches in the same Target string:

@\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}@0.0.0.0@ @http://@https://@

More examples
These 2 examples both accomplish the same replacement using different delimiters:

,http://serverX.domain.com/,https://VirtualServer.domain.com/,,http://serverY.domain.com/,https://VirtualServer.domain.com/,
and
@http://serverX.domain.com/@https://VirtualServer.domain.com/@@http://serverY.domain.com/@https://VirtualServer.domain.com/@

(Note that  /  .  and  :  would NOT be appropriate delimiters for this replacement, since they already appear in the Target string.)

To replace embedded email addresses, you can use any delimiter but "." or "@", with the resulting Target string:
&j.karlsson@dontsendmespam.com&jonas@yourhost.com& &d.allen@dontsendmespam.com&deb@yourhost.com&

Caveats & tips

  • LTM v9.1 is required to use the built-in stream profile for multiple replacement strings.
  • LTM v9.2 is required to use the iRules STREAM::expression command for multiple replacement strings.
  • A stream profile must be associated with the virtual server before an iRule calling the Stream profile can be associated with the virtual server.  The default stream profile (with all parameters blank) may be used.
  • The stream profile performs all replacements in single pass, so data changed once will not be changed again in the same operation even if it matches another replacement pattern after the initial replacement.
  • On LTM versions prior to 9.4, if the HTTP content length may change as a result of the stream replacement, you must enable a HTTP profile with Response Chunking set to Re-chunk to accommodate the content length change on the fly. Otherwise, LTM will forward the now-incorrect Content-Length header, which can cause the browser to hang, display partial pages, or otherwise act funky.
  • Since HTTP compression on the server will prevent LTM from reading the data stream and performing the intended replacement, you may need to use LTM's http profile settings to remove the Accept-Encoding header in the request to prevent compression by the server.
  • The stream profile is case sensitive. Basic regex may do the trick if case insensitivity is required.
  • Start, Separate, AND End each find/replace pair with an appropriate delimiter. (There will be 2 delimiters between pairs.)
  • Leave the "Source" field BLANK when configuring the profile.
  • Optional: Insert whitespace between search/replace pairs -- behavior is the same, improves readability. (Do NOT insert extra whitespace within the replacement pairs.)