apache / apache/apisix

bug: cannot set apisix.extra_lua_path in tests via yaml_config or extra_yaml_config

Open
#12,389 2 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Lua
Stars
17.1k
Forks
2.9k
Avg merge
3d 16h
Merged PRs (30d)
63

Description

### Current Behavior

#### The Issue

When creating a test file for a custom plugin, it's currently not possible to set a custom path for plugins, via `--- yaml_config` or `--- extra_yaml_config`.

#### The Cause

The issue is caused by the snippet below:
https://github.com/apache/apisix/blob/77dacda31277a31d6014b4970e36bae2a5c30907/t/APISIX.pm#L272-L275

This is different from the following, where we put the content of field `apisix.extra_lua_path` config at the beginning of `lua_package_path`:

https://github.com/apache/apisix/blob/77dacda31277a31d6014b4970e36bae2a5c30907/apisix/cli/ngx_tpl.lua#L270-L276

### Expected Behavior

I'd like to be able to set a custom path for APISIX plugins, as we have for APISIX runtime via `apisix.extra_lua_path`. Example:

```yaml
apisix:
extra_lua_path: "/usr/local/apisix/apisix/plugins/custom/?.lua"
```

With this configuration, we can place custom plugins in `/usr/local/apisix/apisix/plugins/custom/apisix/plugins/` and APISIX will load them.

### Error Logs

_No response_

### Steps to Reproduce

#### Minimal Reproducible Example

File `${apisix_home}/apisix/custom/apisix/plugins/myplugin.lua` (simple custom plugin):

```lua
local plugin_name = "myplugin"
local core = require("apisix.core")

local schema = {
type = "object",
properties = {
message = {
type = "string",
default = "Hello World!\n",
}
}
}

local _M = {
version = 0.1,
priority = 0,
name = plugin_name,
schema = schema,
}

function _M.check_schema(conf, _)
return core.schema.check(schema, conf)
end

function _M.access(conf, _)
return 200, conf.message
end

return _M
```

Test file `t/custom/plugin/extra_path.t`:

```perl
use t::APISIX 'no_plan';

repeat_each(1);
no_root_location();
run_tests;

__DATA__

=== TEST 1: Check apisix.extra_lua_path
Verify that the extra Lua path is included in lua_package_path
--- extra_yaml_config
apisix:
extra_lua_path: "/usr/local/apisix/apisix/plugins/custom/?.lua"
--- config
location /t {
content_by_lua_block {
ngx.say("Content of lua_package_path: ", package.path)
}
}
--- request
GET /t
--- response_body_like
.+/usr/local/apisix/apisix/plugins/custom/.+

=== TEST 2: Try loading the custom plugin "myplugin"
Verify that the custom plugin can be loaded.
--- extra_lua_path: /usr/local/apisix/apisix/custom/?.lua
--- extra_yaml_config
plugins:
- myplugin
--- config
location /t {
content_by_lua_block {
local plugin = require("apisix.plugins.myplugin")

ngx.say("done")
}
}
--- request
GET /t
--- response_body
done

```

If we run the test we obtain the following:

```bash
t/custom/plugin/extra_path.t .. 1/?
# Failed test 't/custom/plugin/extra_path.t TEST 1: Check apisix.extra_lua_path - response_body_like - response is expected (Content of lua_package_path: /usr/local/apisix/?.lua;/usr/local/apisix/?/init.lua;/usr/local/apisix/deps/share/lua/5.1/?/init.lua;/usr/local/apisix/deps/share/lua/5.1/?.lua;/usr/local/apisix/apisix/?.lua;/usr/local/apisix/t/?.lua;/usr/local/apisix/t/xrpc/?.lua;/usr/local/apisix/t/xrpc/?/init.lua;/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua;)'
# at /usr/local/apisix/../test-nginx/lib/Test/Nginx/Socket.pm line 1731.
# 'Content of lua_package_path: /usr/local/apisix/?.lua;/usr/local/apisix/?/init.lua;/usr/local/apisix/deps/share/lua/5.1/?/init.lua;/usr/local/apisix/deps/share/lua/5.1/?.lua;/usr/local/apisix/apisix/?.lua;/usr/local/apisix/t/?.lua;/usr/local/apisix/t/xrpc/?.lua;/usr/local/apisix/t/xrpc/?/init.lua;/usr/local/openresty/site/lualib/?.ljbc;/usr/local/openresty/site/lualib/?/init.ljbc;/usr/local/openresty/lualib/?.ljbc;/usr/local/openresty/lualib/?/init.ljbc;/usr/local/openresty/site/lualib/?.lua;/usr/local/openresty/site/lualib/?/init.lua;/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/?/init.lua;./?.lua;/usr/local/openresty/luajit/share/luajit-2.1/?.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;/usr/local/openresty/luajit/share/lua/5.1/?.lua;/usr/local/openresty/luajit/share/lua/5.1/?/init.lua;
# '
# doesn't match '(?^s:.+/usr/local/apisix/apisix/plugins/custom/.+
# )'

# Failed test 't/custom/plugin/extra_path.t TEST 2: Try loading the custom plugin "myplugin" - response_body - response is expected (repeated req 0, req 0)'
# at /usr/local/apisix/../test-nginx/lib/Test/Nginx/Socket.pm line 1685.
# got: ''
# expected: 'done
# '

# Failed test 't/custom/plugin/extra_path.t TEST 2: Try loading the custom plugin "myplugin" - pattern "[error]" should not match any line in error.log but matches line "2025/06/30 08:57:23 [error] 638#638: *2 [lua] plugin.lua:144: load_plugin(): failed to load plugin [myplugin] err: module 'apisix.plugins.myplugin' not found:" (req 0)
# no field package.preload['apisix.plugins.myplugin']
# no file '/usr/local/apisix/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/apisix/plugins/myplugin/init.lua'
# no file '/usr/local/apisix/deps/share/lua/5.1/apisix/plugins/myplugin/init.lua'
# no file '/usr/local/apisix/deps/share/lua/5.1/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/apisix/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/t/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/t/xrpc/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/t/xrpc/apisix/plugins/myplugin/init.lua'
# '
# at /usr/local/apisix/../test-nginx/lib/Test/Nginx/Socket.pm line 1356.

# Failed test 't/custom/plugin/extra_path.t TEST 2: Try loading the custom plugin "myplugin" - pattern "[error]" should not match any line in error.log but matches line "2025/06/30 08:57:23 [error] 637#637: *1 [lua] plugin.lua:144: load_plugin(): failed to load plugin [myplugin] err: module 'apisix.plugins.myplugin' not found:" (req 0)
# no field package.preload['apisix.plugins.myplugin']
# no file '/usr/local/apisix/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/apisix/plugins/myplugin/init.lua'
# no file '/usr/local/apisix/deps/share/lua/5.1/apisix/plugins/myplugin/init.lua'
# no file '/usr/local/apisix/deps/share/lua/5.1/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/apisix/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/t/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/t/xrpc/apisix/plugins/myplugin.lua'
# no file '/usr/local/apisix/t/xrpc/apisix/plugins/myplugin/init.lua'
# '
# at /usr/local/apisix/../test-nginx/lib/Test/Nginx/Socket.pm line 1356.
t/custom/plugin/extra_path.t .. Failed 4/7 subtests

Test Summary Report
-------------------
t/custom/plugin/extra_path.t (Wstat: 0 Tests: 7 Failed: 4)
Failed tests: 2, 5-7
Parse errors: No plan found in TAP output
Files=1, Tests=7, 0 wallclock secs ( 0.01 usr 0.00 sys + 0.18 cusr 0.07 csys = 0.26 CPU)
Result: FAIL
```

As we can see, both tests fail:

- `lua_package_path` doesn't include `/usr/local/apisix/apisix/plugins/custom/?.lua`
- APISIX cannot load custom plugin `myplugin`: `load_plugin(): failed to load plugin [myplugin]`

### Environment

- APISIX version (run `apisix version`): 3.13.0

Contributor guide

Open the contributing guide

Research direction

Start with the test harness logic in t/APISIX.pm at the linked lines and compare it with apisix/cli/ngx_tpl.lua at the linked lines. Run t/custom/plugin/extra_path.t to reproduce both failures. Done means yaml_config or extra_yaml_config makes the configured path appear in lua_package_path and allows myplugin to load.

Written by the indexing model from the issue text.

Assessment

Tech stack
lua, perl
Domain
backend, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.