Associating a content rewrite profile with an HTTP(S) virtual service enables modification of HTML content within the body of a server response. A content rewrite policy can be created and attached to a virtual service through the VMware NSX Advanced Load Balancer CLI or using an API.

A content rewrite profile specifies one or more strings to be searched for within the body of the server response. The profile modifies neither the client requests nor the server headers. Headers can be modified using other features such as DataScripts or policies. For more information about rewriting response headers, see HTTP Response Policy under Virtual Service Policies.

In VMware NSX Advanced Load Balancer, the only way to modify the server response is through the content rewrite profile. The content rewrite profile can be configured as a sub-field in the virtual service. The profile contains a list of key-value pairs to match and replace strings in the response body. Content-rewrite allows you to configure literal strings or variables that are either:

  • Defined in the DataScript using avi.http.set_reqvar().

  • Defined internally for common virtual service or HTTP request parameters like $vs_name, $vs_ip, $http_host, $req_id, and so on.

  • Defined as capture groups of the regex that matched some data in the response

Best Practices for Searching

  • Content rewriting can be computationally expensive. Therefore, it is recommended limiting the search-replace to specific content types that must be modified. The rewritable_content_ref argument is used to specify a string group, which contains a list of eligible content types. By default, the VMware NSX Advanced Load Balancer configurations include the System-Rewritable-Content-Types string group, a list containing common text-based HTML MIME types such as text/html, text/plain, and so on. This ensures that base64-encoded content, such as images are not inspected when performing search-replace operations.

  • Search is conducted throughout the entire body of the eligible server response, with no length limit.

  • If a search string is found in multiple locations within a single HTTP response body, it will be replaced in all those locations.

  • Multiple search-replace pairs can be specified in a single content rewrite profile. All are actively and independently applied. The content replacement is not recursive. For example, consider a profile having a search-replace of “a” with “b”, and a second search-replace of “b” with “c”. Only pre-existing instances of “b” in the server response will be replaced with “c". Instances of “a” that are replaced with “b” are not recursively checked and replaced with “c”. So, with both pairs applied, a server response body of abca would be rewritten to bccb.

  • Searches are not case sensitive.

Search String Types

There are four types of search strings within the response body:

Literal String

Exactly matches the string value to search and replace

Avi Variable
  • There are predefined variables that can be used that contain the values of HTTP headers (like Host, User-Agent, or Cookie) or specific parameters of the request or Virtual Service (like VS IP, VS name, request ID, etc.).

  • The value of the variable will be the string used for searching.

  • If the variable does not exist, then there is no data to search for and the associated replacement string will not be seen in the rewritten response.

  • Set the type to SEARCH_AVI_VAR, and then input the name of the variable to use.

DataScript Variable
  • DataScript can be used to generate a search string.

  • Create and attach a new DataScript to the virtual service.

  • It must use the function to specify the new value. For example, a call to avi.http.set_reqvar(“key1”, “value1”) creates a variable named key1 and sets it to value1.

  • In the content rewrite profile, set the type to SEARCH_DATASCRIPT_VAR and the variable to key1.

  • With each HTTP request, the DataScript can uniquely set the DataScript variable to key1 and assign it a new value (e.g., value1, value2, and so on), based on the script logic.

  • The value set for this DataScript variable will be the string used to search for.

Regular Expression
  • Configure a PCRE compatible regular expression as a search string.

  • This will allow you to search for all matches to this regular expression in the response body.

  • The regular expression may contain capture groups that could be used in the corresponding replacement string.

Replacement String Types

The found strings can be replaced with new strings through one of three methods used to specify the new string.

Literal String

Basic text strings to be used for replacing data found in response bodies.

Avi Variable
  • Set the type to AVI_VAR, and then input the name of the variable to use.

  • The value of the variable will be used to replace the found string.

  • If the variable does not exist, then the value used in the replacement string will be empty, effectively removing the search string from the response.

  • The list of variables are as follows:

Name

Description

client_ip

The source (client’s) IP address (V4 or V6)

client_port

The client port from which the request was sent

client_userid

The username sent in the client request

host

The server header value

http_cookie

The cookie header values

http_host

The host header value

http_referer

The referer header value

http_user_agent

The user-Agent header value

http_via

The via header value

http_x_forwarded_for

The X-Forwarded-For header values

horizon_blast_port

he Horizon server port for Blast protocol traffic

horizon_l7_port

The Horizon server port for primary protocol traffic

horizon_pcoip_port

The Horizon server port for PCOIP protocol traffic

poolname

The Name of the pool in use

request_id

The request ID

DataScript Variable
  • DataScript variables can also be used as the replacement string. The content rewrite profile will replace the searched string with null data, effectively removing the searched string from the response if:

    • No DataScript has been assigned to the virtual service

    • The variable is set to a different name

    • No variable has been set.

Combination String
  • Allows for crafting a string that can be a mix of literal strings and variables.

  • This allows for adding text along with variable names that can be parsed into their respective value.For instance, the virtual service IP and port are ${vs_ip}:${vs_port}.

  • Here the variables are vs_ip and vs_port and will be replaced with the virtual service’s IP address and port respectively.

  • The variables are determined by the variable name within ${}.

  • If the variable is not defined, you can use the empty string in its place.

  • Combination Strings can also access regex captures groups using the variables ${1} ,${2} ,…, ${n}.

Search and Replace Pairs

1. Replace all instances of the user-agent in the response with “Avi”.

+----------------------+-----------------+
| Field                | Value           |
+----------------------+-----------------+
| pairs[1]             |                 |
|   search_string      |                 |
|     type             | SEARCH_AVI_VAR  |
|     val              | http_user_agent |
|   replacement_string |                 |
|     type             | LITERAL_STRING  |
|     val              | Avi             |
+----------------------+-----------------+

2. Replace the address and port in the server response with the VS IP and VS port.

+----------------------+------------------------------------------------+
| Field                | Value                                          |
+----------------------+------------------------------------------------+
| pairs[1]             |                                                | 
|   search_string      |                                                |
|     type             | SEARCH_REGEX                                   |
|     val              | (address:)[\s]*(?:[0-9]{1,3}\.)                |
|                      | {3}[0-9]{1,3}[\s]*                             |
|   replacement_string |                                                |
|     type             | COMBINATION_STRING                             |
|     val              | ${1}${vs_ip}                                   |
| pairs[2]             |                                                |
|   search_string      |                                                |
|     type             | SEARCH_REGEX                                   |
|     val              | (port:)[\s]*\d{1,5}[\s]*                       |
|   replacement_string |                                                |
|     type             | COMBINATION_STRING                             |
|     val              | ${1}${vs_port}                                 |
+----------------------+------------------------------------------------+

Configuring Content Rewrite

In the following terminal, notice these operative fields within the virtual service object named VS3:

  • content_rewrite.rewritable_content_ref

  • content_rewrite.request_rewrite_enabled

  • content_rewrite.response_rewrite_enabled

  • content_rewrite.rsp_match_replace_pair.match_string

  • content_rewrite.rsp_match_replace_pair.replacement_string.type

  • content_rewrite.rsp_match_replace_pair.replacement_string.val

We have inserted [TAB][TAB] in the below terminal to indicate the user’s typing of 2 tabs, causing the shell to reveal command-line syntax.

[admin:1234]: > configure virtualservice vs-1
Updating an existing object. Currently, the object is:
+------------------------------------+----------------------------------+
| Field                              | Value                            |                                     
+------------------------------------+----------------------------------+
| uuid                               | virtualservice-eac16467-fca-4e31-|                                    |                                    |bc0a-5fb3e6bdef19                 |
| name                               | vs-1                             |                                           
| enabled                            | False                            |                                               
| services[1]                        |                                  |                                                   
|   port                             | 80                               |                                                 
|   enable_ssl                       | False                            |                                         
|   port_range_end                   | 80                               |                                              
|   enable_http2                     | False                            |                                               
|   horizon_internal_ports           | False                            |                                           
|   is_active_ftp_data_port          | False                            |                                              
|----------------------------Truncated Output---------------------------|
| content_rewrite                    |                                  |                                                 
|   rewritable_content_ref           | System-Rewritable-Content-Types  |                     
| sideband_profile                   |                                  |                                                
|   sideband_max_request_body_size   | 1024 bytes                       |                                          
| vsvip_ref                          | vs-1-VsVip                       |                                        
| use_vip_as_snat                    | False                            |                                            
| error_page_profile_ref             | Custom-Error-Page-Profile        |                           
| traffic_enabled                    | True                             |
| allow_invalid_client_cert          | False                            |                                              
| vh_type                            | VS_TYPE_VH_SNI                   |                                    
+------------------------------------+----------------------------------+
[admin:1234]: virtualservice> content_rewrite
[admin:1234]: virtualservice:content_rewrite> where
Tenant: admin
Cloud: Default-Cloud
+------------------------+---------------------------------+
| Field                  | Value                           |
+------------------------+---------------------------------+
| rewritable_content_ref | System-Rewritable-Content-Types |
+------------------------+---------------------------------+
[admin:1234]: virtualservice:content_rewrite> rsp_rewrite_rules
New object being created
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> enable
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> index 1
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> name "rewrite-rule-1"
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> where
Tenant: admin
Cloud: Default-Cloud
+--------+----------------+
| Field  | Value          |
+--------+----------------+
| name   | rewrite-rule-1 |
| enable | True           |
| index  | 1              |
+--------+----------------+
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> pairs
New object being created
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> search_string type search_literal_string val ABC
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:search_string> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> replacement_string type literal_string val XYZ
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:replacement_string> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> where
Tenant: admin
Cloud: Default-Cloud
+--------------------+-----------------------+
| Field              | Value                 |
+--------------------+-----------------------+
| search_string      |                       |
|   type             | SEARCH_LITERAL_STRING |
|   val              | ABC                   |
| replacement_string |                       |
|   type             | LITERAL_STRING        |
|   val              | XYZ                   |
+--------------------+-----------------------+
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> pairs
New object being created
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> search_string type search_literal_string val httpvar
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:search_string> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> replacement_string type avi_var val http_host
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:replacement_string> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> where
Tenant: admin
Cloud: Default-Cloud
+--------------------+-----------------------+
| Field              | Value                 |
+--------------------+-----------------------+
| search_string      |                       |
|   type             | SEARCH_LITERAL_STRING |
|   val              | httpvar               |
| replacement_string |                       |
|   type             | AVI_VAR               |
|   val              | http_host             |
+--------------------+-----------------------+
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> pairs
New object being created
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> search_string
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:search_string> type search_regex
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:search_string> val "()[\s]*(?:https://)?[\w\.-]*:443[\s]*()"
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:search_string> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> replacement_string
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:replacement_string> type combination_string
val[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:replacement_string> val "${1}https://${uag_fqdn}:${horizon_l7_port}${2}"
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs:replacement_string> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> where
Tenant: admin
Cloud: Default-Cloud
+--------------------+--------------------------------------------------+
| Field              | Value                                            |                                                    
+--------------------+--------------------------------------------------+
| search_string      |                                                  |                                                                                                       
|   type             | SEARCH_REGEX                                     |                                           
|   val              | (UAG:)[\s]*(?:https://)?[\w\.-]*:443[\s]*        |                 
| replacement_string |                                                  |                                                           
|   type             | COMBINATION_STRING                               |                                       
|   val              | ${1}https://${uag_fqdn}:${vs_port}               |                          
+--------------------+--------------------------------------------------+
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules:pairs> save
[admin:1234]: virtualservice:content_rewrite:rsp_rewrite_rules> save
[admin:1234]: virtualservice:content_rewrite> where
Tenant: admin
Cloud: Default-Cloud
+------------------------+----------------------------------------------+
| Field                  | Value                                        |                                                
+------------------------+----------------------------------------------+
| rewritable_content_ref | System-Rewritable-Content-Types              |                            
| rsp_rewrite_rules[1]   |                                              |                                                          
|   name                 | rewrite-rule-1                               |                                            
|   enable               | True                                         |                                                  
|   index                | 1                                            |                                                        
|   pairs[1]             |                                              |                                                         
|     search_string      |                                              |                                                           
|       type             | SEARCH_LITERAL_STRING                        |                                    
|       val              | ABC                                          |                                                   
|     replacement_string |                                              |                                                          
|       type             | LITERAL_STRING                               |                                         
|       val              | XYZ                                          |                                                    
|   pairs[2]             |                                              |                                                           
|     search_string      |                                              |                                                         
|       type             | SEARCH_LITERAL_STRING                        |                                    
|       val              | httpvar                                      |                                            
|     replacement_string |                                              |                                                        
|       type             | AVI_VAR                                      |                                                  
|       val              | http_host                                    |                                                 
|   pairs[3]             |                                              |                                                          
|     search_string      |                                              |                                                 
|       type             | SEARCH_REGEX                                 |                                          
|       val              | (UAG:)[\s]*(?:https://)?[\w\.-]*:443[\s]*    |                 
|     replacement_string |                                              |                                                         
|       type             | COMBINATION_STRING                           |                                       
|       val              | ${1}https://${uag_fqdn}:${vs_port}           |                       
+------------------------+----------------------------------------------+
[admin:1234]: virtualservice:content_rewrite> save
[admin:1234]: virtualservice> save
+------------------------------------+----------------------------------+
| Field                              | Value                            |                                                    
+------------------------------------+----------------------------------+
| uuid                               | virtualservice-eac16467-fca-4e31-| 
|                                    |bc0a-5fb3e6bdef19                 |
| name                               | vs-1                             |                                                 
| enabled                            | False                            |                                                   
| services[1]                        |                                  |                                                                                    
|   port                             | 80                               |                                                                                   
|   enable_ssl                       | False                            |                                                     
|   port_range_end                   | 80                               |                                                
|   enable_http2                     | False                            |                                                     
|   horizon_internal_ports           | False                            |                                                                      
|   is_active_ftp_data_port          | False                            |                                                     
|-----------------------------Truncated Output--------------------------|
| content_rewrite                    |                                  |                                                          
|   rewritable_content_ref           | System-Rewritable-Content-Types  |                             
|   rsp_rewrite_rules[1]             |                                  |                                                        
|     name                           | rewrite-rule-1                   |                                            
|     enable                         | True                             |                                                      
|     index                          | 1                                |                                                       
|     pairs[1]                       |                                  |                                                      
|       search_string                |                                  |                                                        
|         type                       | SEARCH_LITERAL_STRING            |                                    
|         val                        | ABC                              |                                                    
|       replacement_string           |                                  |                                                           
|         type                       | LITERAL_STRING                   |                                           
|         val                        | XYZ                              |                                                   
|     pairs[2]                       |                                  |                                                           
|       search_string                |                                  |                                                        
|         type                       | SEARCH_LITERAL_STRING            |                                     
|         val                        | httpvar                          |                                                
|       replacement_string           |                                  |                                                         
|         type                       | AVI_VAR                          |                                             
|         val                        | http_host                        |                                                
|     pairs[3]                       |                                  |                                                        
|       search_string                |                                  |                                                         
|         type                       | SEARCH_REGEX                     |                                         
|         val                        | (UAG:)[\s]*(?:https://)?         |
|                                    |[\w\.-]*:443[\s]*                 |                 
|       replacement_string           |                                  |                                                         
|         type                       | COMBINATION_STRING               |                                        
|         val                        |${1}https://${uag_fqdn}:${vs_port}|                         
|-----------------------------Truncated Output--------------------------|