0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-09-29 20:28:52 +02:00

modules/client/rooms/state: Refactor GET handlers for chunk streaming and spec behavior.

This commit is contained in:
Jason Volk 2019-03-14 14:25:37 -07:00
parent 42309c1c96
commit 8ebb51bd9f

View file

@ -13,72 +13,29 @@
using namespace ircd::m;
using namespace ircd;
static resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id,
const string_view &event_id);
static resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id,
const string_view &event_id,
const string_view &type);
static resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id,
const string_view &event_id,
const string_view &type,
const string_view &state_key);
resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id)
{
char type_buf[m::event::TYPE_MAX_SIZE];
const string_view &type
{
url::decode(type_buf, request.parv[2])
};
char skey_buf[m::event::STATE_KEY_MAX_SIZE];
const string_view &state_key
{
url::decode(skey_buf, request.parv[3])
};
// (non-standard) Allow an event_id to be passed in the query string
// for reference framing.
char evid_buf[m::id::MAX_SIZE];
const string_view &event_id
{
url::decode(evid_buf, request.query["event_id"])
};
if(type && state_key)
return get__state(client, request, room_id, event_id, type, state_key);
if(type)
return get__state(client, request, room_id, event_id, type);
return get__state(client, request, room_id, event_id);
}
resource::response
put__state(client &client,
const resource::request &request,
const room::id &room_id)
{
if(request.parv.size() < 3)
throw m::NEED_MORE_PARAMS
{
"'type' path parameter required."
};
char type_buf[m::event::TYPE_MAX_SIZE];
const string_view &type
{
url::decode(type_buf, request.parv[2])
};
if(request.parv.size() < 3)
throw m::NEED_MORE_PARAMS
{
"'state_key' path parameter required."
};
char skey_buf[m::event::STATE_KEY_MAX_SIZE];
const string_view &state_key
{
@ -104,89 +61,109 @@ put__state(client &client,
};
}
static resource::response
get__state(client &client,
const resource::request &request,
const m::room::state &state);
resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id,
const string_view &event_id)
const room::id &room_id)
{
const room::state state
char type_buf[m::event::TYPE_MAX_SIZE];
const string_view &type
{
room{room_id, event_id}
url::decode(type_buf, request.parv[2])
};
std::vector<json::value> ret;
ret.reserve(32);
state.for_each([&ret]
(const event &event)
char skey_buf[m::event::STATE_KEY_MAX_SIZE];
const string_view &state_key
{
ret.emplace_back(event);
url::decode(skey_buf, request.parv[3])
};
// (non-standard) Allow an event_id to be passed in the query string
// for reference framing.
m::event::id::buf event_id;
if(request.query["event_id"])
url::decode(event_id, request.query["event_id"]);
const m::room room
{
room_id, event_id
};
if(!exists(room))
throw m::NOT_FOUND
{
"Room %s not found.",
string_view{room_id}
};
if(!room.visible(request.user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view %s",
string_view{room_id}
};
const m::room::state state
{
room
};
if(!type)
return get__state(client, request, state);
m::event::fetch::opts fopts;
fopts.query_json_force = true;
const m::event::fetch event
{
state.get(type, state_key), fopts
};
if(!visible(event, request.user_id))
throw m::ACCESS_DENIED
{
"You are not permitted to view this state in %s",
string_view{room_id}
};
return resource::response
{
client, event.source
};
}
resource::response
get__state(client &client,
const resource::request &request,
const m::room::state &state)
{
resource::response::chunked response
{
client, http::OK
};
json::stack out
{
response.buf, response.flusher()
};
json::stack::array top
{
out
};
state.for_each([&request, &top]
(const m::event &event)
{
if(!visible(event, request.user_id))
return;
top.append(event);
});
return resource::response
{
client, json::value
{
ret.data(), ret.size()
}
};
}
resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id,
const string_view &event_id,
const string_view &type)
{
const room::state state
{
room{room_id, event_id}
};
std::vector<json::value> ret;
ret.reserve(32);
state.for_each(type, [&ret]
(const event &event)
{
ret.emplace_back(event);
});
return resource::response
{
client, json::value
{
ret.data(), ret.size()
}
};
}
resource::response
get__state(client &client,
const resource::request &request,
const room::id &room_id,
const string_view &event_id,
const string_view &type,
const string_view &state_key)
{
const room::state state
{
room{room_id, event_id}
};
std::array<json::value, 1> ret;
const bool i{state.get(std::nothrow, type, state_key, [&ret]
(const event &event)
{
ret[0] = event;
})};
return resource::response
{
client, json::value
{
ret.data(), i
}
};
return response;
}