Separate out api url parser

This commit is contained in:
2025-09-04 16:36:10 -04:00
parent 55069c0c79
commit 2278694f4f
7 changed files with 417 additions and 219 deletions

View File

@@ -0,0 +1,117 @@
#include <doctest/doctest.h>
#include "api_url_parser.hpp"
TEST_CASE("ApiUrlParser routing") {
SUBCASE("Static GET routes") {
auto match = ApiUrlParser::parse("GET", "/v1/version");
CHECK(match.route == HttpRoute::GetVersion);
match = ApiUrlParser::parse("GET", "/v1/subscribe");
CHECK(match.route == HttpRoute::GetSubscribe);
match = ApiUrlParser::parse("GET", "/metrics");
CHECK(match.route == HttpRoute::GetMetrics);
match = ApiUrlParser::parse("GET", "/ok");
CHECK(match.route == HttpRoute::GetOk);
}
SUBCASE("Static POST routes") {
auto match = ApiUrlParser::parse("POST", "/v1/commit");
CHECK(match.route == HttpRoute::PostCommit);
}
SUBCASE("Not found") {
auto match = ApiUrlParser::parse("GET", "/unknown/route");
CHECK(match.route == HttpRoute::NotFound);
match = ApiUrlParser::parse("DELETE", "/v1/version");
CHECK(match.route == HttpRoute::NotFound);
}
}
TEST_CASE("ApiUrlParser with query strings") {
SUBCASE("Simple query string") {
auto match = ApiUrlParser::parse("GET", "/v1/status?request_id=123");
CHECK(match.route == HttpRoute::GetStatus);
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::RequestId)]
.has_value());
CHECK(
match.params[static_cast<size_t>(ApiParameterKey::RequestId)].value() ==
"123");
}
SUBCASE("Multiple query parameters") {
auto match =
ApiUrlParser::parse("GET", "/v1/status?request_id=abc&min_version=42");
CHECK(match.route == HttpRoute::GetStatus);
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::RequestId)]
.has_value());
CHECK(
match.params[static_cast<size_t>(ApiParameterKey::RequestId)].value() ==
"abc");
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::MinVersion)]
.has_value());
CHECK(match.params[static_cast<size_t>(ApiParameterKey::MinVersion)]
.value() == "42");
}
SUBCASE("Unknown parameters are ignored") {
auto match = ApiUrlParser::parse("GET", "/v1/version?foo=bar&baz=quux");
CHECK(match.route == HttpRoute::GetVersion);
CHECK_FALSE(match.params[static_cast<size_t>(ApiParameterKey::RequestId)]
.has_value());
}
}
TEST_CASE("ApiUrlParser with URL parameters") {
SUBCASE("PUT retention policy") {
auto match = ApiUrlParser::parse("PUT", "/v1/retention/my-policy");
CHECK(match.route == HttpRoute::PutRetention);
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::PolicyId)]
.has_value());
CHECK(
match.params[static_cast<size_t>(ApiParameterKey::PolicyId)].value() ==
"my-policy");
}
SUBCASE("DELETE retention policy") {
auto match = ApiUrlParser::parse("DELETE", "/v1/retention/another-policy");
CHECK(match.route == HttpRoute::DeleteRetention);
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::PolicyId)]
.has_value());
CHECK(
match.params[static_cast<size_t>(ApiParameterKey::PolicyId)].value() ==
"another-policy");
}
SUBCASE("GET retention policy") {
auto match = ApiUrlParser::parse("GET", "/v1/retention/get-this");
CHECK(match.route == HttpRoute::GetRetention);
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::PolicyId)]
.has_value());
CHECK(
match.params[static_cast<size_t>(ApiParameterKey::PolicyId)].value() ==
"get-this");
}
SUBCASE("GET all retention policies (no ID)") {
auto match = ApiUrlParser::parse("GET", "/v1/retention");
CHECK(match.route == HttpRoute::GetRetention);
CHECK_FALSE(match.params[static_cast<size_t>(ApiParameterKey::PolicyId)]
.has_value());
}
}
TEST_CASE("ApiUrlParser with URL and query parameters") {
auto match = ApiUrlParser::parse("DELETE", "/v1/retention/p1?wait=true");
CHECK(match.route == HttpRoute::DeleteRetention);
REQUIRE(
match.params[static_cast<size_t>(ApiParameterKey::PolicyId)].has_value());
CHECK(match.params[static_cast<size_t>(ApiParameterKey::PolicyId)].value() ==
"p1");
REQUIRE(match.params[static_cast<size_t>(ApiParameterKey::Wait)].has_value());
CHECK(match.params[static_cast<size_t>(ApiParameterKey::Wait)].value() ==
"true");
}