haproxy-api-rs icon indicating copy to clipboard operation
haproxy-api-rs copied to clipboard

Getting proxies from core object fails due to use of special meta methods

Open jgoodson opened this issue 1 month ago • 0 comments

The Core object contains methods for extracting proxies/frontends/backends but these do not seem to work. What happens is that these methods use the mlua Table.pairs() method on tables which return some AnyUserData which can't be converted to a LuaTable and so throws an error.

This happens because the underlying tables for these core fields aren't normal Lua tables and instead use custom meta methods to implement __pairs and provide dynamic results. The mlua pairs() method specifically does not use the __pairs meta method, so the data isn't normally accessible.

You can extract and cast these successfully to Proxy structs if you use the underlying __pairs implementation directly. I threw together a quick iterator using the actual __pairs metamethod since I couldn't find any way to use it via mlua, though I may be missing something.

pub(crate) struct Pairs<T> {
    next: LuaFunction,
    _phantom: PhantomData<T>,
}

impl<T> Pairs<T> {
    pub(crate) fn from(tbl: &LuaTable) -> LuaResult<Self> {
        Ok(Self {
            next: tbl
                .metatable()
                .unwrap()
                .get::<LuaFunction>("__pairs")
                .unwrap()
                .call::<LuaFunction>(tbl)
                .unwrap(),
            _phantom: PhantomData,
        })
    }
}

impl<T> Iterator for Pairs<T>
where
    T: FromLuaMulti,
{
    type Item = (LuaString, T);

    fn next(&mut self) -> Option<Self::Item> {
        self.next.call::<(LuaString, T)>(()).ok()
    }
}

Using this allows you to iterate over the proxies/frontends/backends tables as intended and can also be used for the Servers inside of the proxy.servers tables which have the same issue and potentially other fields I haven't noticed yet.

jgoodson avatar Oct 16 '25 20:10 jgoodson