Skip to content

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

@mikyll

Description

@mikyll

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:

apisix/t/APISIX.pm

Lines 272 to 275 in 77dacda

my $lua_deps_path = $block->lua_deps_path // <<_EOC_;
lua_package_path "$apisix_home/?.lua;$apisix_home/?/init.lua;$apisix_home/deps/share/lua/5.1/?/init.lua;$apisix_home/deps/share/lua/5.1/?.lua;$apisix_home/apisix/?.lua;$apisix_home/t/?.lua;$apisix_home/t/xrpc/?.lua;$apisix_home/t/xrpc/?/init.lua;;";
lua_package_cpath "$apisix_home/?.so;$apisix_home/deps/lib/lua/5.1/?.so;$apisix_home/deps/lib64/lua/5.1/?.so;;";
_EOC_

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:

# put extra_lua_path in front of the builtin path
# so user can override the source code
lua_package_path "{*extra_lua_path*}$prefix/deps/share/lua/5.1/?.lua;$prefix/deps/share/lua/5.1/?/init.lua;]=]
.. [=[{*apisix_lua_home*}/?.lua;{*apisix_lua_home*}/?/init.lua;;{*lua_path*};";
lua_package_cpath "{*extra_lua_cpath*}$prefix/deps/lib64/lua/5.1/?.so;]=]
.. [=[$prefix/deps/lib/lua/5.1/?.so;;]=]
.. [=[{*lua_cpath*};";

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:

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):

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:

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:

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    Status

    📋 Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions