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]