From ab2dab8ffc8a424451f85f3b3dc672f83ece1043 Mon Sep 17 00:00:00 2001 From: lxbme <18108274905@163.com> Date: Fri, 6 Mar 2026 16:30:51 +0800 Subject: [PATCH 1/3] fix: disable automatic type conversion for env vars in apisix.yaml - 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 #12932 --- apisix/cli/file.lua | 13 +++-- t/cli/test_standalone.sh | 117 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 5 deletions(-) diff --git a/apisix/cli/file.lua b/apisix/cli/file.lua index 36873631a84c..28412de286d6 100644 --- a/apisix/cli/file.lua +++ b/apisix/cli/file.lua @@ -90,7 +90,10 @@ local function var_sub(val) end -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 + end local new_keys = {} for key, val in pairs(conf) do -- avoid re-iterating the table for already iterated key @@ -111,7 +114,7 @@ local function resolve_conf_var(conf) end end if type(val) == "table" then - local ok, err = resolve_conf_var(val) + local ok, err = resolve_conf_var(val, enable_type_conversion) if not ok then return nil, err end @@ -123,7 +126,7 @@ local function resolve_conf_var(conf) return nil, err end - if var_used then + if var_used and enable_type_conversion then if tonumber(new_val) ~= nil then new_val = tonumber(new_val) elseif new_val == "true" then @@ -255,7 +258,7 @@ function _M.read_yaml_conf(apisix_home) return nil, "invalid config.yaml file" end - local ok, err = resolve_conf_var(user_conf) + local ok, err = resolve_conf_var(user_conf, true) if not ok then return nil, err end @@ -304,7 +307,7 @@ function _M.read_yaml_conf(apisix_home) if apisix_conf_yaml then local apisix_conf = yaml.load(apisix_conf_yaml) if apisix_conf then - local ok, err = resolve_conf_var(apisix_conf) + local ok, err = resolve_conf_var(apisix_conf, false) if not ok then return nil, err end diff --git a/t/cli/test_standalone.sh b/t/cli/test_standalone.sh index d5844a2ce654..a398fc741582 100755 --- a/t/cli/test_standalone.sh +++ b/t/cli/test_standalone.sh @@ -155,3 +155,120 @@ if [ $expected_config_reloads -ne $actual_config_reloads ]; then exit 1 fi echo "passed: apisix.yaml was not reloaded" + + +# test: environment variable with large number should be preserved as string +echo ' +apisix: + enable_admin: false +deployment: + role: data_plane + role_data_plane: + config_provider: yaml +' > conf/config.yaml + +echo ' +routes: + - + uri: /test-large-number + plugins: + openid-connect: + client_id: "${{APISIX_CLIENT_ID}}" + client_secret: "secret" + discovery: "http://example.com/.well-known/openid-configuration" + upstream: + nodes: + "127.0.0.1:9091": 1 + type: roundrobin +#END +' > conf/apisix.yaml + +# Test with large number that exceeds Lua double precision +APISIX_CLIENT_ID="356002209726529540" make init + +if ! APISIX_CLIENT_ID="356002209726529540" make run > output.log 2>&1; then + cat output.log + echo "failed: large number in env var should not cause type conversion error" + exit 1 +fi + +sleep 0.1 + +# Verify the service is running (should not have validation errors) +code=$(curl -o /dev/null -s -m 5 -w %{http_code} http://127.0.0.1:9080/test-large-number) +if [ $code -eq 500 ]; then + echo "failed: large number env var was converted to scientific notation" + exit 1 +fi + +make stop +sleep 0.5 + +echo "passed: large number in env var preserved as string in apisix.yaml" + +# test: quoted numeric env vars in apisix.yaml should remain strings +echo ' +apisix: + enable_admin: false +deployment: + role: data_plane + role_data_plane: + config_provider: yaml +' > conf/config.yaml + +echo ' +routes: + - + uri: /test-quoted + plugins: + proxy-rewrite: + headers: + X-Custom-ID: "${{NUMERIC_ID}}" + upstream: + nodes: + "127.0.0.1:9091": 1 + type: roundrobin +#END +' > conf/apisix.yaml + +NUMERIC_ID="12345" make init +NUMERIC_ID="12345" make run +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 + echo "failed: quoted numeric env var in apisix.yaml should work" + exit 1 +fi + +make stop +sleep 0.5 + +echo "passed: quoted numeric env var preserved as string in apisix.yaml" + +# test: config.yaml should still support type conversion +echo ' +routes: [] +#END +' > conf/apisix.yaml + +echo ' +apisix: + 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" + +git checkout conf/config.yaml +git checkout conf/apisix.yaml \ No newline at end of file From 6e128b243f5c9ede8c248eda0f3ff8d54c91c30a Mon Sep 17 00:00:00 2001 From: lxbme <18108274905@163.com> Date: Sat, 7 Mar 2026 00:05:25 +0800 Subject: [PATCH 2/3] fix: update config_yaml.lua to disable type conversion for apisix.yaml - 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 --- apisix/core/config_yaml.lua | 2 +- t/cli/test_standalone.sh | 56 ++++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/apisix/core/config_yaml.lua b/apisix/core/config_yaml.lua index d0443f256f43..188c3fce3cf2 100644 --- a/apisix/core/config_yaml.lua +++ b/apisix/core/config_yaml.lua @@ -153,7 +153,7 @@ local function update_config(table, conf_version) return end - local ok, err = file.resolve_conf_var(table) + local ok, err = file.resolve_conf_var(table, false) if not ok then log.error("failed to resolve variables:" .. err) return diff --git a/t/cli/test_standalone.sh b/t/cli/test_standalone.sh index a398fc741582..054353ee69b4 100755 --- a/t/cli/test_standalone.sh +++ b/t/cli/test_standalone.sh @@ -156,6 +156,8 @@ if [ $expected_config_reloads -ne $actual_config_reloads ]; then fi echo "passed: apisix.yaml was not reloaded" +make stop +sleep 0.5 # test: environment variable with large number should be preserved as string echo ' @@ -172,10 +174,8 @@ routes: - uri: /test-large-number plugins: - openid-connect: - client_id: "${{APISIX_CLIENT_ID}}" - client_secret: "secret" - discovery: "http://example.com/.well-known/openid-configuration" + response-rewrite: + body: "${{APISIX_CLIENT_ID}}" upstream: nodes: "127.0.0.1:9091": 1 @@ -194,10 +194,10 @@ fi sleep 0.1 -# Verify the service is running (should not have validation errors) -code=$(curl -o /dev/null -s -m 5 -w %{http_code} http://127.0.0.1:9080/test-large-number) -if [ $code -eq 500 ]; then - echo "failed: large number env var was converted to scientific notation" +# Verify the response body matches the exact large numeric string +body=$(curl -s -m 5 http://127.0.0.1:9080/test-large-number) +if [ "$body" != "356002209726529540" ]; then + echo "failed: large number env var was not preserved as string, got: $body" exit 1 fi @@ -221,9 +221,8 @@ routes: - uri: /test-quoted plugins: - proxy-rewrite: - headers: - X-Custom-ID: "${{NUMERIC_ID}}" + response-rewrite: + body: "${{NUMERIC_ID}}" upstream: nodes: "127.0.0.1:9091": 1 @@ -235,9 +234,9 @@ NUMERIC_ID="12345" make init NUMERIC_ID="12345" make run 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 - echo "failed: quoted numeric env var in apisix.yaml should work" +body=$(curl -s -m 5 http://127.0.0.1:9080/test-quoted) +if [ "$body" != "12345" ]; then + echo "failed: quoted numeric env var in apisix.yaml was not preserved as string, got: $body" exit 1 fi @@ -246,7 +245,7 @@ sleep 0.5 echo "passed: quoted numeric env var preserved as string in apisix.yaml" -# test: config.yaml should still support type conversion +# test: config.yaml should still support type conversion (boolean) echo ' routes: [] #END @@ -254,21 +253,32 @@ routes: [] echo ' apisix: - node_listen: ${{NODE_PORT}} + enable_admin: ${{ENABLE_ADMIN}} deployment: - role: data_plane - role_data_plane: + role: traditional + role_traditional: config_provider: yaml + etcd: + host: + - "http://127.0.0.1:2379" ' > conf/config.yaml -NODE_PORT=9080 make init +ENABLE_ADMIN=false make init +ENABLE_ADMIN=false make run +sleep 0.1 -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" +# If type conversion works, enable_admin is boolean false and admin API is disabled (404) +# If type conversion fails, enable_admin stays string "false" which is truthy, admin API is enabled +code=$(curl -o /dev/null -s -m 5 -w %{http_code} http://127.0.0.1:9080/apisix/admin/routes) +if [ "$code" -eq 200 ]; then + echo "failed: boolean env var in config.yaml was not converted, admin API should be disabled" exit 1 fi -echo "passed: config.yaml still converts numeric env vars correctly" +make stop +sleep 0.5 + +echo "passed: config.yaml still converts boolean env vars correctly" git checkout conf/config.yaml -git checkout conf/apisix.yaml \ No newline at end of file +git checkout conf/apisix.yaml From 1eb3c437197671dc642b46422370003b9b269742 Mon Sep 17 00:00:00 2001 From: lxbme <18108274905@163.com> Date: Mon, 9 Mar 2026 14:35:36 +0800 Subject: [PATCH 3/3] fix: improve test assertions for env var type conversion tests - Check for explicit 404 status when admin API is disabled - Capture both HTTP status code and response body for /test-large-number - Add proper error diagnostics when assertions fail --- t/cli/test_standalone.sh | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/t/cli/test_standalone.sh b/t/cli/test_standalone.sh index 054353ee69b4..a575368e5c29 100755 --- a/t/cli/test_standalone.sh +++ b/t/cli/test_standalone.sh @@ -176,6 +176,7 @@ routes: plugins: response-rewrite: body: "${{APISIX_CLIENT_ID}}" + status_code: 200 upstream: nodes: "127.0.0.1:9091": 1 @@ -195,7 +196,12 @@ fi sleep 0.1 # Verify the response body matches the exact large numeric string -body=$(curl -s -m 5 http://127.0.0.1:9080/test-large-number) +code=$(curl -o /tmp/response_body -s -m 5 -w %{http_code} http://127.0.0.1:9080/test-large-number) +body=$(cat /tmp/response_body) +if [ "$code" -ne 200 ]; then + echo "failed: expected 200 for /test-large-number, but got: $code, body: $body" + exit 1 +fi if [ "$body" != "356002209726529540" ]; then echo "failed: large number env var was not preserved as string, got: $body" exit 1 @@ -223,6 +229,7 @@ routes: plugins: response-rewrite: body: "${{NUMERIC_ID}}" + status_code: 200 upstream: nodes: "127.0.0.1:9091": 1 @@ -234,7 +241,12 @@ NUMERIC_ID="12345" make init NUMERIC_ID="12345" make run sleep 0.1 -body=$(curl -s -m 5 http://127.0.0.1:9080/test-quoted) +code=$(curl -o /tmp/response_body -s -m 5 -w %{http_code} http://127.0.0.1:9080/test-quoted) +body=$(cat /tmp/response_body) +if [ "$code" -ne 200 ]; then + echo "failed: expected 200 for /test-quoted, but got: $code, body: $body" + exit 1 +fi if [ "$body" != "12345" ]; then echo "failed: quoted numeric env var in apisix.yaml was not preserved as string, got: $body" exit 1 @@ -270,8 +282,8 @@ sleep 0.1 # If type conversion works, enable_admin is boolean false and admin API is disabled (404) # If type conversion fails, enable_admin stays string "false" which is truthy, admin API is enabled code=$(curl -o /dev/null -s -m 5 -w %{http_code} http://127.0.0.1:9080/apisix/admin/routes) -if [ "$code" -eq 200 ]; then - echo "failed: boolean env var in config.yaml was not converted, admin API should be disabled" +if [ "$code" -ne 404 ]; then + echo "failed: expected 404 when admin API is disabled, but got: $code" exit 1 fi