Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions apisix/admin/standalone.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ local events = require("apisix.events")
local core = require("apisix.core")
local config_yaml = require("apisix.core.config_yaml")
local config_validate = require("apisix.admin.config_validate")
local file = require("apisix.cli.file")

local ALL_RESOURCE_KEYS = config_validate.get_all_resource_keys()

Expand Down Expand Up @@ -327,6 +328,16 @@ function _M.init_worker()
-- this table is generated by json decode, so there is no need to clone it
config[METADATA_LAST_MODIFIED] = nil
config[METADATA_DIGEST] = nil

-- resolve ${{VAR}} / $ENV:// references in the config pushed via the
-- Admin API. The file-based standalone path resolves these in
-- config_yaml.parse(), but the Admin API path decodes JSON straight
-- into _update_config and would otherwise keep them literal.
local ok, err = file.resolve_conf_var(config)
if not ok then
core.log.error("failed to resolve variables in config: ", err)
return
end
config_yaml._update_config(config)
end
events:register(update_config, EVENT_UPDATE, EVENT_UPDATE)
Expand Down
33 changes: 33 additions & 0 deletions t/admin/standalone.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,4 +944,37 @@ describe('Validate API - Standalone', () => {
});
});
});

describe('Variable resolution', () => {
it('resolves ${{VAR}} references in config pushed via the Admin API', async () => {
mockDigest += 1;
const config = {
routes: [
{
id: 'r_var',
uri: '/r_var',
upstream: {
nodes: { '127.0.0.1:1980': 1 },
type: 'roundrobin',
},
// The proxy-rewrite uri uses a ${{VAR:=default}} reference. The
// gateway must resolve it to the default ("/hello"); if it were
// left literal, the upstream would receive "${{...}}" instead of
// "/hello" and would not return the hello body.
plugins: {
'proxy-rewrite': { uri: '${{STANDALONE_ENV_TEST:=/hello}}' },
},
},
],
};
const putResp = await client.put(ENDPOINT, config, {
headers: { [HEADER_DIGEST]: mockDigest },
});
expect(putResp.status).toEqual(202);

const resp = await client.get('/r_var');
expect(resp.status).toEqual(200);
expect(resp.data).toEqual('hello world\n');
});
});
});
Loading