Repository navigation
Description
Current behavior
Updating an existing rule to handle: "" persists a non-null empty string and publishes a rule UPDATE, but multiple gateway rule handlers keep their previous cached configuration:
- The empty string passes
Optional.ofNullable(handle). GsonUtils.fromJson("", Handle.class)returns null.CommonHandleCache.cachedHandle(key, null)ignores the write rather than removing the existing entry.- Plugin execution still obtains and applies the previous handle.
Locations / reachable update path
- RuleServiceImpl.update():194–229 validates/persists the update and publishes it. Plugin-specific rule-handle validation here only applies to agent-gateway, not the four plugins below.
- rule-sqlmap.xml:378–380 writes a handle whenever the bound value is non-null, including an empty string. H2/MySQL/PostgreSQL can retain that empty-string value.
- CommonHandleCache.java:47–49 ignores null cache values.
- RequestPluginHandler.java:40–45 and the same pattern in RewritePluginDataHandler, ModifyResponsePluginDataHandler and ParamMappingPluginDataHandler.
This is explicitly an empty-string update, not an omitted/null field that intentionally retains its database value during a selective update.
Reproduction / validation
A probe compiled the current RequestPlugin, RequestHandle, affected data handlers and CommonHandleCache. It configured a header mutation, updated the same rule to an empty handle, and executed the actual RequestPlugin doExecute() path. A {} update is the passing clear/no-op control:
HANDLE={"header":{"setHeaders":{"X-Old":"still-active"}}} X-Old=still-active
HANDLE=<empty> X-Old=still-active
HANDLE={} X-Old=null
GSON_EMPTY_IS_NULL=true
REWRITE_OLD_HANDLE_RETAINED=true
MODIFY_RESPONSE_OLD_HANDLE_RETAINED=true
PARAM_MAPPING_OLD_HANDLE_RETAINED=true
The latter three controls seed a real handle via each actual handler and verify the same object remains after the empty update. Independent reviewers traced the Admin persistence/event path and corrected an initial mistaken assumption that Gson returns a default object for an empty string. No deployed Admin/database/gateway integration was run; persistence and event propagation are source-confirmed, while handler/cache/request behavior is executed.
Impact / suggested fix
Operators can clear a rule's stored configuration while gateways continue applying old request/header/path/body transformations until a later valid handle update or cache reset. Treat an explicitly cleared handle as a cache eviction or normalized empty configuration, and keep all affected handlers consistent. Preserve the distinction between explicit empty clears and omitted fields in selective Admin updates; do not turn every missing DTO field into a runtime clear.
Related existing work
#6772/#6880 concern removeRule deletion callbacks, whereas this is the UPDATE path. #7750 concerns selector logging sampling after {}, not rule-handle parsing. #6507 concerns partial RequestHandle fields, and #4142 is an old frontend JWT-handle editing symptom. The four same-root handlers are grouped here to avoid separate duplicate reports.
Reviewed revision
Apache ShenYu 2.7.2-SNAPSHOT, master@66d7d954ca37d651a5ad916f988a8081157a7ab4. Priority P2 / Medium, high confidence in the described source/runtime behavior. Unit-test and CI issue categories excluded.
Activity
fix(plugin): evict cached rule handles when explicitly cleared. (apac…