Wasm match_rule doesn't work after reroute triggered in a previous plugin in 2.2.0

View original issue on GitHub  ·  Variant 3

Higress Wasm Plugin Match Rules Failing After Rerouting in Version 2.2.0

In Higress version 2.2.0, a critical issue arises when using Wasm plugins in conjunction with request rerouting. Specifically, if a Wasm plugin (Plugin A) modifies request headers in a way that triggers a reroute to a different route, subsequent Wasm plugins (Plugin B) may fail to correctly apply their match_rule configurations associated with the new route. This results in Plugin B operating with the configuration intended for the original route, leading to unexpected behavior and potentially incorrect request processing.

Root Cause Analysis

The root cause of this issue lies in how Higress (specifically, the underlying Envoy proxy) resolves the ROUTE_NAME property within the Wasm plugin context. When Plugin A reroutes the request, the clearRouteCache() function is called. However, this function only clears the cached route within the ActiveStream, but it doesn't update the streamInfo().route_, which is used by the getRouteName() function. Consequently, when Plugin B attempts to retrieve the route name, it retrieves the stale, original route name instead of the newly resolved route name.

The critical code snippet in context.cc is:


case PropertyToken::ROUTE_NAME:
    if (info && !info->getRouteName().empty()) {       // ← Path 1: STALE
      return CelValue::CreateString(&info->getRouteName());
    }
    if (filter_callbacks) {
      auto route = filter_callbacks->route();          // ← Path 2: CORRECT (never reached)
      if (route) {
        return CelValue::CreateString(&route->routeName());
      }
    }
    break;

Because info->getRouteName() (Path 1) always returns the stale route name, the correct path (Path 2), which would re-evaluate the route, is never reached.

Proposed Solution

The proposed solution involves prioritizing the filter_callbacks->route() call when resolving the ROUTE_NAME. This ensures that the route is re-evaluated after a reroute event, allowing subsequent plugins to operate with the correct route configuration.

The corrected code snippet would be:


case PropertyToken::ROUTE_NAME:
    if (filter_callbacks) {
      auto route = filter_callbacks->route();
      if (route) {
        return CelValue::CreateString(&route->routeName());
      }
    }
    if (info && !info->getRouteName().empty()) {
      return CelValue::CreateString(&info->getRouteName());
    }
    break;

By moving the filter_callbacks check to the top, the code prioritizes obtaining the route from the current filter callbacks, which will reflect the updated route after a reroute has occurred. The original info->getRouteName() call is retained as a fallback for cases where filter_callbacks is unavailable.

Practical Considerations and Best Practices

By understanding the root cause and implementing the proposed solution, you can mitigate the risk of encountering this issue and ensure the correct and consistent operation of your Wasm plugins in Higress.