Runtime error running dispatcher.lookup

I have similar code in the controller and now that I've tried 19.07.0 myself I just tested it in the console:

> dispatcher = require "luci.dispatcher"
> = dispatcher.lookup("admin/vpn")
/usr/lib/lua/luci/dispatcher.lua:749: attempt to index field 'treecache' (a nil value)
stack traceback:
        /usr/lib/lua/luci/dispatcher.lua:749: in function </usr/lib/lua/luci/dispatcher.lua:739>
        (tail call): ?
        [C]: ?

Am I doing something wrong?

The dispatcher requires a number of initializations before you can invoke index functions within it. In particular you need to provide an HTTP request mock and set fake paths.

Try this code:

http = require "luci.http"
dispatcher = require "luci.dispatcher"

http.context.request = http.Request({}, function() end, function() end)

dispatcher.context.path = { "admin" }
dispatcher.context.request = { "admin" }
dispatcher.createindex()
dispatcher.createtree()

print(dispatcher.lookup("admin/vpn"))

Thank you. Should I use the exactly same code for controller when I'm trying to figure out if node exists? I've asked previously, you recommended I use dispatcher.lookup, given the amount of preparation needed, I feel I should confirm.

Within a controller index() function you do not need these extra preparations as they happen implicitly before that function is reached. But if you want to use it on the CLI, outside of the HTTP request/response context, you do have to bootstrap the dispatcher manually.

Uhm, I don't know what's going on then. This is the code I have:

module("luci.controller.vpn-policy-routing", package.seeall)
function index()
	if nixio.fs.access("/etc/config/vpn-policy-routing") then
		local node = "services"
		if luci.dispatcher.lookup("admin/vpn") then node = "vpn" end
		entry({"admin", node, "vpn-policy-routing"}, cbi("vpn-policy-routing"), _("VPN Policy Routing"))
		entry({"admin", node, "vpn-policy-routing", "action"}, call("vpn_policy_routing_action"), nil).leaf = true
	end
end

And on 19.07 with OpenVPN showing up in the VPN node, vpn-policy-routing still shows under services.

Another thing on 19.07 the cbi/tblsection is formatting some columns really weird: the first few have shrunk and the last three are unnecessarily large as can be seen here.

That's a bug in the unsupported material theme. Try Bootstrap or OpenWrt.

1 Like

Thank you, it's working fine with theme-openwrt.

Can you see anything wrong in a piece of code from my controller above tho? Even if I can get the VPR to show under VPN node if I flush luci cache, it doesn't consistently stay there. I don't want it to show under the VPN node unless it exists tho. Any suggestions?

I'll look into that

Edit: okay, in hindsight its obvious why it doesn't work. Since the index() functions are executed while the menu tree is getting built, the lookup() will not work as the tree is not assembled yet.

I don't think that there is any solution to figure out the VPN node at run time. The best workaround I can think of atm is to simply provide an alias so that the package appears in both menus:

entry({"admin", "vpn", "vpn-policy-routing"}, alias("admin", "services", "vpn-policy-routing"))

If the VPN node does not exist, the alias will have no effect.

Thanks, I've tried:

module("luci.controller.vpn-policy-routing", package.seeall)
function index()
	if nixio.fs.access("/etc/config/vpn-policy-routing") then
		entry({"admin", "services", "vpn-policy-routing"}, cbi("vpn-policy-routing"), _("VPN Policy Routing"))
		entry({"admin", "vpn", "vpn-policy-routing"}, alias("admin", "services", "vpn-policy-routing"))
		entry({"admin", "services", "vpn-policy-routing", "action"}, call("vpn_policy_routing_action"), nil).leaf = true
	end
end

And it doesn't produce an entry in the VPN node on 19.07.0-rc1 (with OpenVPN being in the VPN node) either. If I just replace the alias with another cbi call it works tho.
Should I just see if the luci-app-openvpn is installed and then use the VPN node?