fix: disable automatic type conversion for env vars in apisix.yaml#13078
fix: disable automatic type conversion for env vars in apisix.yaml#13078lxbme wants to merge 2 commits intoapache:masterfrom
Conversation
- Add optional parameter 'enable_type_conversion' to resolve_conf_var function - Disable type conversion when processing apisix.yaml in standalone mode - Keep type conversion enabled for config.yaml to maintain backward compatibility - Add test cases for large numeric strings and type preservation This fixes the issue where environment variables containing large numbers (exceeding Lua's double precision) were automatically converted to scientific notation in standalone mode, causing validation errors in plugins like openid-connect. Fixes apache#12932
There was a problem hiding this comment.
Pull request overview
This PR addresses an issue in standalone mode where environment-variable substitutions in apisix.yaml were automatically type-converted (e.g., large numeric strings becoming scientific-notation numbers), leading to schema validation failures in plugins like openid-connect.
Changes:
- Added an
enable_type_conversionparameter toresolve_conf_varto control env-var type casting. - Disabled type conversion when parsing
apisix.yamlvia the CLI path, while keeping it enabled forconfig.yaml. - Added standalone-mode CLI tests intended to cover large numeric strings and type preservation.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
apisix/cli/file.lua |
Adds a flag to control env-var type conversion and disables conversion for CLI parsing of apisix.yaml. |
t/cli/test_standalone.sh |
Adds regression tests for large numeric env var handling and attempts to ensure config.yaml conversion remains enabled. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
t/cli/test_standalone.sh
Outdated
| node_listen: ${{NODE_PORT}} | ||
| deployment: | ||
| role: data_plane | ||
| role_data_plane: | ||
| config_provider: yaml | ||
| ' > conf/config.yaml | ||
|
|
||
| NODE_PORT=9080 make init | ||
|
|
||
| if ! grep "listen 0.0.0.0:9080" conf/nginx.conf > /dev/null; then | ||
| echo "failed: numeric env var in config.yaml should be converted to number" | ||
| exit 1 | ||
| fi | ||
|
|
||
| echo "passed: config.yaml still converts numeric env vars correctly" | ||
|
|
There was a problem hiding this comment.
Grepping for listen 0.0.0.0:9080 doesn't prove type conversion is still happening, since both a string and a number can render identically in nginx.conf. To validate conversion is preserved for config.yaml, assert a type-sensitive field (e.g., apisix.enable_admin: ${{ENABLE_ADMIN}} with ENABLE_ADMIN=false and verify the admin API is disabled) or otherwise check a value that would fail schema validation if left as a string.
| node_listen: ${{NODE_PORT}} | |
| deployment: | |
| role: data_plane | |
| role_data_plane: | |
| config_provider: yaml | |
| ' > conf/config.yaml | |
| NODE_PORT=9080 make init | |
| if ! grep "listen 0.0.0.0:9080" conf/nginx.conf > /dev/null; then | |
| echo "failed: numeric env var in config.yaml should be converted to number" | |
| exit 1 | |
| fi | |
| echo "passed: config.yaml still converts numeric env vars correctly" | |
| enable_admin: ${{ENABLE_ADMIN}} | |
| deployment: | |
| role: data_plane | |
| role_data_plane: | |
| config_provider: yaml | |
| ' > conf/config.yaml | |
| ENABLE_ADMIN=false make init | |
| ENABLE_ADMIN=false make run | |
| sleep 1 | |
| if curl -s -o /dev/null http://127.0.0.1:9180/apisix/admin/routes; then | |
| echo "failed: admin API should be disabled when ENABLE_ADMIN=false in config.yaml" | |
| make stop | |
| exit 1 | |
| fi | |
| make stop | |
| echo "passed: config.yaml still converts boolean env vars correctly" |
| local function resolve_conf_var(conf) | ||
| local function resolve_conf_var(conf, enable_type_conversion) | ||
| if enable_type_conversion == nil then | ||
| enable_type_conversion = true |
There was a problem hiding this comment.
resolve_conf_var now defaults enable_type_conversion to true, but apisix/core/config_yaml.lua calls file.resolve_conf_var(table) when reloading apisix.yaml in standalone mode. That means type conversion is still enabled at runtime for apisix.yaml, so the large-number/scientific-notation issue will persist unless that call site is updated to pass false (or otherwise disable conversion for apisix.yaml).
| enable_type_conversion = true | |
| enable_type_conversion = false |
There was a problem hiding this comment.
I'd prefer keeping the default enable_type_conversion = true to ensure backward compatibility. Since _M.resolve_conf_var is a public function, changing the global default would silently break existing callers (like config.yaml processing) that rely on type conversion.
Because this fix is specific to apisix.yaml in standalone mode, it's safer for those specific call sites to explicitly opt out by passing false. I'll also add file.resolve_conf_var(table, false) to update_config() in apisix/core/config_yaml.lua to handle runtime reloads.
t/cli/test_standalone.sh
Outdated
| openid-connect: | ||
| client_id: "${{APISIX_CLIENT_ID}}" | ||
| client_secret: "secret" | ||
| discovery: "http://example.com/.well-known/openid-configuration" |
There was a problem hiding this comment.
This test uses openid-connect with a placeholder discovery URL and then treats an HTTP 500 as evidence of type conversion. That can be flaky because 500s may come from plugin runtime behavior (failed discovery fetch, etc.) rather than config type conversion. Consider switching to a plugin with no external dependencies (e.g., response-rewrite with body: ${{APISIX_CLIENT_ID}}) and assert the response body matches the exact large numeric string (not scientific notation).
| openid-connect: | |
| client_id: "${{APISIX_CLIENT_ID}}" | |
| client_secret: "secret" | |
| discovery: "http://example.com/.well-known/openid-configuration" | |
| response-rewrite: | |
| body: "${{APISIX_CLIENT_ID}}" |
t/cli/test_standalone.sh
Outdated
| if [ $code -eq 500 ]; then | ||
| echo "failed: large number env var was converted to scientific notation" |
There was a problem hiding this comment.
The curl assertion only fails on status 500, so it will still pass if APISIX isn't reachable (000) or if the route wasn't loaded due to schema validation (404). To make the test reliable, assert a known-success status (typically 200) and/or explicitly fail if curl returns 000/404.
| if [ $code -eq 500 ]; then | |
| echo "failed: large number env var was converted to scientific notation" | |
| if [ "$code" != "200" ]; then | |
| echo "failed: expected 200 from /test-large-number, got $code (large number env var may have caused an error)" |
t/cli/test_standalone.sh
Outdated
| sleep 0.1 | ||
|
|
||
| code=$(curl -s -H "Host: test.com" http://127.0.0.1:9080/test-quoted -o /dev/null -w %{http_code}) | ||
| if [ ! $code -eq 404 ] && [ ! $code -eq 200 ]; then |
There was a problem hiding this comment.
This check allows 404, which can mask a failure to load the route (e.g., schema validation failing because the env var was converted to a number). To actually validate behavior, assert 200 for a known-working upstream, or check the error log for the absence of schema/type-validation errors.
| if [ ! $code -eq 404 ] && [ ! $code -eq 200 ]; then | |
| if [ "$code" -ne 200 ]; then |
- Pass false to resolve_conf_var in config_yaml.lua update_config() to disable type conversion at runtime for apisix.yaml - Improve test cases: use response-rewrite plugin for deterministic body assertions, use boolean type conversion test for config.yaml
|
Here's a summary of the changes I have pushed in the newest commit: Code fix:
Test improvements:
|
This fixes the issue where environment variables containing large numbers (exceeding Lua's double precision) were automatically converted to scientific notation in standalone mode, causing validation errors in plugins like openid-connect.
Fixes #12932
Description
This PR fixes the automatic type conversion issue for environment variables in standalone mode
apisix.yaml.When using environment variables in
apisix.yaml(standalone mode), numeric string values were automatically converted to numbers. This caused issues when:356002209726529540)3.5600220972653e+17)openid-connectplugin'sclient_id)Which issue(s) this PR fixes:
Fixes #12932
Checklist
(No documentation update needed - this is an internal bug fix with no user-facing configuration changes)