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/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 d5844a2ce654..a575368e5c29 100755 --- a/t/cli/test_standalone.sh +++ b/t/cli/test_standalone.sh @@ -155,3 +155,142 @@ if [ $expected_config_reloads -ne $actual_config_reloads ]; then exit 1 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 ' +apisix: + enable_admin: false +deployment: + role: data_plane + role_data_plane: + config_provider: yaml +' > conf/config.yaml + +echo ' +routes: + - + uri: /test-large-number + plugins: + response-rewrite: + body: "${{APISIX_CLIENT_ID}}" + status_code: 200 + 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 response body matches the exact large numeric string +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 +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: + response-rewrite: + body: "${{NUMERIC_ID}}" + status_code: 200 + 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 -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 +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 (boolean) +echo ' +routes: [] +#END +' > conf/apisix.yaml + +echo ' +apisix: + enable_admin: ${{ENABLE_ADMIN}} +deployment: + role: traditional + role_traditional: + config_provider: yaml + etcd: + host: + - "http://127.0.0.1:2379" +' > conf/config.yaml + +ENABLE_ADMIN=false make init +ENABLE_ADMIN=false make run +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" -ne 404 ]; then + echo "failed: expected 404 when admin API is disabled, but got: $code" + exit 1 +fi + +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