152 lines
3.9 KiB
C++
152 lines
3.9 KiB
C++
namespace code::seafire::resources
|
|
{
|
|
|
|
bool
|
|
check_preconditions(
|
|
server::request_t& req,
|
|
server::response_t& res,
|
|
representation::BasicRepresentation auto const& r)
|
|
{
|
|
namespace rfc7232 = protocol::rfc7232;
|
|
|
|
using representation_traits = representation::traits::representation_traits<decltype(r)>;
|
|
|
|
if (auto if_match = get<rfc7232::if_match_t>(req); if_match) {
|
|
if constexpr (representation_traits::has_entity_tag) {
|
|
bool match = check_if_match(req, res, r, *if_match);
|
|
|
|
if (!match) {
|
|
res.send(server::common_error_t::precondition_failed);
|
|
return false;
|
|
}
|
|
}
|
|
else {
|
|
res.send(server::common_error_t::precondition_failed);
|
|
return false;
|
|
}
|
|
}
|
|
else if (auto if_unmodified_since = get<rfc7232::if_unmodified_since_t>(req); if_unmodified_since) {
|
|
bool match = check_if_unmodified_since(req, res, r, *if_unmodified_since);
|
|
|
|
if (!match) {
|
|
res.send(server::common_error_t::precondition_failed);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (auto if_none_match = get<rfc7232::if_none_match_t>(req); if_none_match) {
|
|
bool match = false;
|
|
|
|
if (!match) {
|
|
if (req.get_message().method() == "GET" || req.get_message().method() == "HEAD")
|
|
res.send(server::common_error_t::not_modified);
|
|
else
|
|
res.send(server::common_error_t::precondition_failed);
|
|
return false;
|
|
}
|
|
}
|
|
else if (auto if_modified_since = get<rfc7232::if_modified_since_t>(req); if_modified_since) {
|
|
bool match = false;
|
|
|
|
if (!match) {
|
|
res.send(server::common_error_t::precondition_failed);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// If-Match
|
|
//
|
|
bool
|
|
check_if_match(
|
|
server::request_t& req,
|
|
server::response_t& res,
|
|
representation::BasicRepresentation auto const& r,
|
|
protocol::rfc7232::if_match_t const& if_match)
|
|
{
|
|
using representation_traits = representation::traits::representation_traits<std::decay_t<decltype(r)>>;
|
|
|
|
if constexpr (representation_traits::has_entity_tag) {
|
|
auto etag = [&r]
|
|
{
|
|
if constexpr (common::traits::is_optional_v<decltype(r.etag())>) {
|
|
return r.etag();
|
|
}
|
|
else {
|
|
return std::optional<protocol::rfc7232::entity_tag_t>{r.etag()};
|
|
}
|
|
}();
|
|
|
|
if (!etag)
|
|
return false;
|
|
|
|
if (if_match.is_anything())
|
|
return true;
|
|
|
|
for (auto const& j : if_match.tags()) {
|
|
if (strong_compare(*etag, j))
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// If-Unmodified-Since
|
|
//
|
|
bool
|
|
check_if_unmodified_since(
|
|
server::request_t& req,
|
|
server::response_t& res,
|
|
representation::BasicRepresentation auto const& r,
|
|
std::chrono::system_clock::time_point const& if_unmodified_since)
|
|
{
|
|
using representation_traits = representation::traits::representation_traits<std::decay_t<decltype(r)>>;
|
|
|
|
if constexpr (representation_traits::has_last_modified) {
|
|
auto last_modified = r.last_modified();
|
|
|
|
if (last_modified <= if_unmodified_since)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// If-None-Match
|
|
//
|
|
bool
|
|
check_if_none_match(
|
|
server::request_t& req,
|
|
server::response_t& res,
|
|
representation::BasicRepresentation auto const& r,
|
|
protocol::rfc7232::if_none_match_t const& if_none_match)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// If-Modified-Since
|
|
//
|
|
bool
|
|
check_if_modified_since(
|
|
server::request_t& req,
|
|
server::response_t& res,
|
|
representation::BasicRepresentation auto const& r,
|
|
std::chrono::system_clock::time_point const& if_modified_since)
|
|
{
|
|
using representation_traits = representation::traits::representation_traits<std::decay_t<decltype(r)>>;
|
|
|
|
if constexpr (representation_traits::has_last_modified) {
|
|
auto last_modified = r.last_modified();
|
|
|
|
if (last_modified >= if_modified_since)
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
} // namespace code::seafire::resources
|