nic-6443 commented on issue #12932:
URL: https://github.com/apache/apisix/issues/12932#issuecomment-4221987929

   ## Analysis: Root Cause and Proposed Fix
   
   ### Root Cause
   
   The current `resolve_conf_var()` in `apisix/cli/file.lua` does env var 
substitution **after** YAML parsing (table-level). At that point, YAML quoting 
context is lost — both `"${{VAR}}"` (quoted) and `${{VAR}}` (unquoted) become 
the same Lua string `"${{VAR}}"`. The code then blindly applies `tonumber()` to 
all substituted values, which:
   
   1. **Breaks string-typed fields** — `client_id: "${{VAR}}"` with `VAR=12345` 
becomes number `12345`, failing schema validation (expects string). This 
affects ANY numeric value, not just large ones.
   2. **Loses precision for large numbers** — `VAR=356002209726529540` → 
`3.5600220972653e+17`.
   3. **Gives users no way to control types** — YAML quotes (the standard 
mechanism) are ignored.
   
   ### Why PR #13078 Does Not Fix This
   
   The `exceeds_lua_precision()` check (skip `tonumber()` for integers >15 
digits) only addresses symptom (2). Short numeric strings like `VAR=12345` in 
string-typed fields are still incorrectly converted. The fundamental problem 
remains: **type conversion is schema-agnostic and happens after YAML type 
context is lost**.
   
   ### Proposed Fix: Text-Level Substitution Before YAML Parsing
   
   Move `${{VAR}}` substitution from **post-parse** (on the Lua table) to 
**pre-parse** (on the raw YAML text), for `apisix.yaml` only. This lets YAML's 
native type rules handle everything correctly:
   
   ```yaml
   client_id: "${{VAR}}"    # VAR=12345   → client_id: "12345"  → string ✓
   retries: ${{RETRIES}}     # RETRIES=3   → retries: 3          → number ✓
   http_to_https: ${{FLAG}}  # FLAG=true   → http_to_https: true → boolean ✓
   node_weight: ${{WEIGHT}}  # WEIGHT=1    → node_weight: 1      → number ✓
   client_id: "${{VAR}}"    # VAR=356...0 → client_id: "356...0" → string ✓
   ```
   
   Users control types through standard YAML quoting — quoted = string, 
unquoted = YAML-inferred type. This is the same approach used by Helm, 
envsubst, and other template tools.
   
   **Scope**: Only `apisix.yaml` in standalone mode (both CLI init and runtime 
reload). `config.yaml` keeps the current table-level substitution unchanged 
(backward compatible).
   
   **Cost**: ~25 lines for a new `resolve_yaml_text_var()` function (same regex 
as existing `var_sub`), 2 call sites updated. Low risk, minimal code change.
   
   **Known considerations** (consistent with Helm/envsubst behavior):
   - Env var values containing YAML special characters (`"`, `\n`, `:`) must be 
used in appropriate YAML quoting context
   - Commented-out `${{VAR}}` patterns will be processed (unlike table-level 
where comments are stripped by YAML parser first)
   - Full YAML implicit typing applies to unquoted substituted values (e.g., 
`on`/`off`/`null`)


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to