Inability to call new prosody plugin API

Hi,
I have written an API as a plugin to get some users information from the prosody service. But the API endpoint is never reached when I try it. This endpoint has worked in the same jitsi installation but after upgrading the jitsi it stopped working.

This is my plugin content.

local jid = require "util.jid";
local json = require "util.json";
local iterators = require "util.iterators";
local array = require"util.array";

local have_async = pcall(require, "util.async");
if not have_async then
    module:log("error", "requires a version of Prosody with util.async");
    return;
end

local async_handler_wrapper = module:require "util".async_handler_wrapper;

local tostring = tostring;
local neturl = require "net.url";
local parse = neturl.parseQuery;

-- option to enable/disable room API token verifications
local enableTokenVerification
    = module:get_option_boolean("enable_roomsize_token_verification", false);

local token_util = module:require "token/util".new(module);
local get_room_from_jid = module:require "util".get_room_from_jid;

-- no token configuration but required
if token_util == nil and enableTokenVerification then
    log("error", "no token configuration but it is required");
    return;
end

-- required parameter for custom muc component prefix,
-- defaults to "conference"
local muc_domain_prefix
    = module:get_option_string("muc_mapper_domain_prefix", "conference");

--- Verifies room name, domain name with the values in the token
-- @param token the token we received
-- @param room_address the full room address jid
-- @return true if values are ok or false otherwise
function verify_token(token, room_address)
    if not enableTokenVerification then
        return true;
    end

    -- if enableTokenVerification is enabled and we do not have token
    -- stop here, cause the main virtual host can have guest access enabled
    -- (allowEmptyToken = true) and we will allow access to rooms info without
    -- a token
    if token == nil then
        log("warn", "no token provided");
        return false;
    end

    local session = {};
    session.auth_token = token;
    local verified, reason = token_util:process_and_verify_token(session);
    if not verified then
        log("warn", "not a valid token %s", tostring(reason));
        return false;
    end

    if not token_util:verify_room(session, room_address) then
        log("warn", "Token %s not allowed to join: %s",
            tostring(token), tostring(room_address));
        return false;
    end

    return true;
end

--- Handles request for retrieving the room participants details
-- @param event the http event, holds the request query
-- @return GET response, containing a json with participants details
function handle_get_room (event)
    if (not event.request.url.query) then
        return { status_code = 400; };
    end

	local params = parse(event.request.url.query);
	local room_name = params["room"];
	local domain_name = params["domain"];
    local subdomain = params["subdomain"];

    local room_address
        = jid.join(room_name, muc_domain_prefix.."."..domain_name);

    if subdomain and subdomain ~= "" then
        room_address = "["..subdomain.."]"..room_address;
    end

    if not verify_token(params["token"], room_address) then
        return { status_code = 403; };
    end

	local room = get_room_from_jid(room_address);
	local participant_count = 0;
	local occupants_json = array();

	log("info", "Querying room %s", tostring(room_address));

    local responseObj = {};

	if room then
		local occupants = room._occupants;

		if occupants then
			participant_count = iterators.count(room:each_occupant());
			for _, occupant in room:each_occupant() do
			    -- filter focus as we keep it as hidden participant
			    if string.sub(occupant.nick,-string.len("/focus"))~="/focus" then
				    for _, pr in occupant:each_session() do
					local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or "";
					local email = pr:get_child_text("email") or "";
					occupants_json:push({
					    jid = tostring(occupant.nick),
					    -- email = tostring(email),
					    employee_id = tostring(nick)});
				    end
			    end
			end
		end

        if participant_count > 1 then
            participant_count = participant_count - 1;
        end

        responseObj = {
            transactionCode = "SUCCESS";
            room = {
                room_name = room_name;
                room_address = room_address;
                users_count = participant_count;
                users = occupants_json;
            }
        };
	else
		responseObj = {
            transactionCode = "FAIL";
            message = "No room found"
        };
	end

	return { status_code = 200; body = json.encode(responseObj); };
end;

function module.load()
    module:depends("http");
	module:provides("http", {
		default_path = "/";
		route = {
			["GET api/room"] = function (event) return async_handler_wrapper(event, handle_get_room) end;
		};
	});
end

This is my nginx entry.

location = /room {
	proxy_pass http://0.0.0.0:5280/room?$args&domain=meet.domain.com;
	proxy_set_header X-Forwarded-For $remote_addr;
	proxy_set_header Host meet.domain.com;
	add_header Content-Type "application/json; charset=UTF-8";
	add_header 'Access-Control-Allow-Origin' '*';
}

The plugin is enabled in the prosody config and all services are running without error. Yet the request is not reaching the plugin.

curl http://0.0.0.0:5280/room?room=3434 results in

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>404 Not Found</title>
<style>
body{
	margin-top:14%;
	text-align:center;
	background-color:#F8F8F8;
	font-family:sans-serif;
}
h1{
	font-size:xx-large;
}
p{
	font-size:x-large;
}
p+p {
	font-size:large;
	font-family:courier;
}
</style>
</head>
<body>
<h1>404 Not Found</h1>
<p>Whatever you were looking for is not here. It&apos;s behind you.</p>
<p>Unknown host: localhost</p>
</body>
</html>

Any guide to resolve this issue will be great. Thanks.

You cannot test this like this. That will always return 404 as you don’t have that endpoint under virtual host names 0.0.0.0

See your nginx config, you are passing a Host header when proxying the connection. That means that the module needs to be loaded under the virtual host named β€œmeet.domain.com”,

1 Like

Thanks @damencho for reaching out even though the issue was in nginx. Actually that was the case.