Redirect Rule in HTTP Request Policy fails when the URI contains "#" or "?" special characters
search cancel

Redirect Rule in HTTP Request Policy fails when the URI contains "#" or "?" special characters

book

Article ID: 451535

calendar_today

Updated On:

Products

VMware Avi Load Balancer

Issue/Introduction

After upgrading to Avi Load Balancer 32.1.x, an HTTP Request Policy configured with a Redirect Action no longer redirects clients to the intended URL when the redirect URI contains special characters.

The special characters in the URI are percent-encoded in the Location header returned to the client:

  • "?" is encoded to %3F
  • "#"  is encoded to %23

As a result, the client browser treats the encoded characters as literal characters in the path rather than as a query-string or fragment delimiter, and the application either fails to load or lands on an incorrect page.

Example:

Configured redirect target:

https://<hostname>:443/directory-path/index.html#/login

Location header actually sent by the Virtual Service:

https://<hostname>:443/directory-path/index.html%23/login

Environment

 

  • VMware Avi Load Balancer
  • Affected versions: 32.1.1 - 32.1.3
  • Virtual Service with an HTTP Request Policy using a Redirect Action whose redirect path contains # or ?

 

Cause

This is a behavior change introduced in the 32.1.x release train. In the affected versions, the Redirect Action of the HTTP Request Policy percent-encodes reserved characters before writing the value into the Location response header. Because # and ? are structural delimiters in a URL, encoding them changes the meaning of the URL and breaks the redirect.

Resolution

Fix Version: Future Maintenance Release on 32.1.x version

Workaround: 

Applicable when the redirect target contains a fragment (#).

  1. Remove (or disable) the existing HTTP Request Policy rule that performs the redirection.
  2. Create a standalone DataScript with an HTTP Request event and attach it to the Virtual Service.

    -- HTTP_REQ event
    local path = avi.http.get_path()
    if path == "/" then
        local loc_hdr = "https://" .. avi.http.hostname() .. ":443/directory-path/index.html#/login"
        avi.http.redirect(loc_hdr)
    end

The DataScript writes the Location header directly and is not subject to the encoding behavior of the Redirect Action.


Workaround 2 — Use the query string field of the Redirect Action with special character "?"

Applicable when the redirect rule only needs to append a query string (for example /Login?test).

The Redirect Action provides a separate field for adding a query string to the Location header. Configure the query string in that field instead of embedding ? in the redirect path. This field behaves the same way as the add_string option available in the Rewrite URL Action rule.

Note: For add_string field config only allow from CLI, UI for the equivalent field not available for the Redirect Action rule in any version.

SSH to Controller Leader Node
# shell
[admin:controller-ip]: > configure httppolicyset VS-Name-HTTPPolicySet-0
Updating an existing object. Currently, the object is:
+------------------------------+----------------------------------------------------+
| Field                        | Value                                              |
+------------------------------+----------------------------------------------------+
| uuid                         | httppolicyset-######                              |
| name                         | VS-HTTPPolicySet-0                                 |
| http_request_policy          |                                                    |
|   rules[1]                   |                                                    |
|     name                     | Rule 1                                             |
|     index                    | 1                                                  |
|     enable                   | True                                               |
|     match                    |                                                    |
|       path                   |                                                    |
|         match_criteria       | EQUALS                                             |
|         match_case           | INSENSITIVE                                        |
|         match_str[1]         | /                                                  |
|         match_decoded_string | True                                               |
|     redirect_action          |                                                    |
|       protocol               | HTTPS                                              |
|       port                   | 443                                                |
|       path                   |                                                    |
|         type                 | URI_PARAM_TYPE_TOKENIZED                           |
|         tokens[1]            |                                                    |
|           type               | URI_TOKEN_TYPE_STRING                              |
|           str_value          | Login                                              |
|       keep_query             | False                                              |
|       status_code            | HTTP_REDIRECT_STATUS_CODE_302                      |
|       add_string             | test                                               |    <<<<<<<<<<<
|     log                      | True                                               |
|     all_headers              | True                                               |

Additional Information

Verify the corrected behavior by inspecting the response headers of the redirect, either from the browser developer tools or with a client-side capture, and confirming that the Location header contains the literal # or ? character.