Files

74 lines
2.4 KiB
C++

#pragma once
#include <iostream>
#include <string_view>
#include <vector>
namespace session::network::backends {
const std::string_view FRAGMENT_PUBKEY = "p";
const std::string_view FRAGMENT_STREAM_ENCRYPTION = "d";
struct MatchedEndpoint {
std::string_view base; // everything before the pattern match (e.g. "https://example.com")
std::vector<std::string_view> captures;
};
static std::optional<MatchedEndpoint> match_endpoint(
std::string_view pattern, std::string_view input) {
if (input.empty())
return {};
auto first_placeholder = pattern.find("{}");
auto static_prefix = fmt::format("/{}", pattern.substr(0, first_placeholder));
auto pattern_start = input.find(static_prefix);
if (pattern_start == std::string_view::npos)
return std::nullopt;
MatchedEndpoint result;
result.base = input.substr(0, pattern_start);
// Skip leading '/' if present, otherwise start from the pattern directly
auto remaining = input.substr(pattern_start);
if (!remaining.empty() && remaining[0] == '/')
remaining = remaining.substr(1);
while (!pattern.empty()) {
auto placeholder = pattern.find("{}");
auto literal = pattern.substr(0, placeholder);
if (!remaining.starts_with(literal))
return std::nullopt;
remaining = remaining.substr(literal.size());
if (placeholder == std::string_view::npos)
break;
pattern = pattern.substr(placeholder + 2);
// Capture up to the next literal segment (or end of path segment if pattern is exhausted)
auto next_literal = pattern.substr(0, pattern.find("{}"));
auto capture_end = next_literal.empty() ? std::min(remaining.find('#'), remaining.find('?'))
: remaining.find(next_literal);
if (capture_end == std::string_view::npos && !next_literal.empty())
return std::nullopt;
// If no fragment/query, capture to end of string
if (capture_end == std::string_view::npos)
capture_end = remaining.size();
auto capture = remaining.substr(0, capture_end);
if (!capture.empty() && capture.back() == '/')
capture.remove_suffix(1);
result.captures.push_back(capture);
remaining = remaining.substr(capture_end);
}
return result;
}
} // namespace session::network::backends