2025-03-07 02:25:53 +01:00

136 lines
3.7 KiB
C++

namespace seafire::resources
{
void
handle(server::request_t& req,
server::response_t& res,
Resource auto const& r)
{
using resource_traits = traits::resource_traits<std::decay_t<decltype(r)>>;
auto const not_allowed = [&req, &res]
{
set<protocol::rfc7231::allow_t>(res, resource_traits::allowed_methods());
res.send(server::common_error_t::method_not_allowed);
};
auto const& method = req.get_message().method();
// GET
//
if (method == "GET" || method == "HEAD") {
if constexpr (resource_traits::is_gettable) {
negotiate<typename resource_traits::get_representation_type>(
req,
res,
[&req, &res, &r](std::optional<protocol::media_type_t> const& accepted_type)
{
handle_get(
req,
res,
r,
accepted_type,
req.get_message().method() == "HEAD" ? get_kind_t::head : get_kind_t::get
);
}
);
return;
}
else {
not_allowed();
}
}
// PUT (update)
//
else if (method == "PUT") {
if constexpr (resource_traits::is_updatable) {
if constexpr (std::is_same_v<void, typename resource_traits::update_result_type>) {
handle_update(req, res, r, std::nullopt);
}
else if constexpr (representation::Representation<typename resource_traits::update_result_type>) {
negotiate<typename resource_traits::update_result_type>(
req,
res,
[&req, &res, &r](std::optional<protocol::media_type_t> const& accepted_type)
{
handle_update(req, res, r, accepted_type);
}
);
}
else {
negotiate<typename traits::resource_traits<typename resource_traits::update_result_type>::get_representation_type>(
req,
res,
[&req, &res, &r](std::optional<protocol::media_type_t> const& accepted_type)
{
handle_update(req, res, r, accepted_type);
}
);
}
}
else {
not_allowed();
}
}
// POST (create)
//
else if (method == "POST") {
if constexpr (resource_traits::is_creatable) {
if constexpr (std::is_same_v<void, typename resource_traits::update_result_type>) {
handle_create(req, res, r, std::nullopt);
}
else if constexpr (representation::Representation<typename resource_traits::create_result_type>) {
negotiate<typename resource_traits::create_result_type>(
req,
res,
[&req, &res, &r](std::optional<protocol::media_type_t> const& accepted_type)
{
handle_create(req, res, r, accepted_type);
}
);
}
else {
using one = typename resource_traits::create_result_type;
using two = typename traits::resource_traits<one>::get_representation_type;
//using resource_traits = traits::resource_traits<
negotiate<two>(
req,
res,
[&req, &res, &r](std::optional<protocol::media_type_t> const& accepted_type)
{
handle_create(req, res, r, accepted_type);
}
);
}
}
else {
not_allowed();
}
}
// DELETE
//
else if (method == "DELETE") {
#if 0
if constexpr (resource_traits::is_erasable) {
handle_erase(tx, r);
return;
}
else {
not_allowed();
}
#endif
}
// method not implemented.
//
else {
res.send(server::common_error_t::not_implemented);
}
}
} // namespace seafire::resources