summaryrefslogtreecommitdiff
path: root/http/utility.hpp
diff options
context:
space:
mode:
authorEd Tanous <edtanous@google.com>2022-08-19 17:00:38 +0300
committerEd Tanous <edtanous@google.com>2022-08-24 00:47:32 +0300
commit7f8d8fa938f521d18278e9cb5673bacd83217d09 (patch)
tree5134ef203f9db67ce142c18fbc23bc22899697ef /http/utility.hpp
parenta3526fee27da0e324cd022ea77d282d1146b3317 (diff)
downloadbmcweb-7f8d8fa938f521d18278e9cb5673bacd83217d09.tar.xz
Allow parsing urls with extra elements
Sometimes it is desirable to only parse a portion of a URL, and allow any elements at the end. This comes up significantly in aggregation where parsing "/redfish/v1/<collection>/anything is pretty common. This commit adds a new class, OrMorePaths, that can be used as a placeholder to indicate that more paths should be accepted. Tested: Unit tests pass. Signed-off-by: Ed Tanous <edtanous@google.com> Change-Id: If4fb3991a91560fd3b8b838f912aa36e79ddd2b3
Diffstat (limited to 'http/utility.hpp')
-rw-r--r--http/utility.hpp47
1 files changed, 38 insertions, 9 deletions
diff --git a/http/utility.hpp b/http/utility.hpp
index e08e565b5b..2ba9b0ea08 100644
--- a/http/utility.hpp
+++ b/http/utility.hpp
@@ -573,6 +573,9 @@ inline boost::urls::url
}
} // namespace details
+class OrMorePaths
+{};
+
template <typename... AV>
inline boost::urls::url urlFromPieces(const AV... args)
{
@@ -584,21 +587,37 @@ namespace details
// std::reference_wrapper<std::string> - extracts segment to variable
// std::string_view - checks if segment is equal to variable
-using UrlSegment =
- std::variant<std::reference_wrapper<std::string>, std::string_view>;
+using UrlSegment = std::variant<std::reference_wrapper<std::string>,
+ std::string_view, OrMorePaths>;
+
+enum class UrlParseResult
+{
+ Continue,
+ Fail,
+ Done,
+};
class UrlSegmentMatcherVisitor
{
public:
- bool operator()(std::string& output)
+ UrlParseResult operator()(std::string& output)
{
output = std::string_view(segment.data(), segment.size());
- return true;
+ return UrlParseResult::Continue;
+ }
+
+ UrlParseResult operator()(std::string_view expected)
+ {
+ if (std::string_view(segment.data(), segment.size()) == expected)
+ {
+ return UrlParseResult::Continue;
+ }
+ return UrlParseResult::Fail;
}
- bool operator()(std::string_view expected)
+ UrlParseResult operator()(OrMorePaths /*unused*/)
{
- return std::string_view(segment.data(), segment.size()) == expected;
+ return UrlParseResult::Done;
}
explicit UrlSegmentMatcherVisitor(
@@ -615,7 +634,7 @@ inline bool readUrlSegments(const boost::urls::url_view& urlView,
{
const boost::urls::segments_view& urlSegments = urlView.segments();
- if (!urlSegments.is_absolute() || segments.size() != urlSegments.size())
+ if (!urlSegments.is_absolute())
{
return false;
}
@@ -625,13 +644,23 @@ inline bool readUrlSegments(const boost::urls::url_view& urlView,
for (const auto& segment : segments)
{
- if (!std::visit(UrlSegmentMatcherVisitor(*it), segment))
+ if (it == end)
+ {
+ // If the request ends with an "any" path, this was successful
+ return std::holds_alternative<OrMorePaths>(segment);
+ }
+ UrlParseResult res = std::visit(UrlSegmentMatcherVisitor(*it), segment);
+ if (res == UrlParseResult::Done)
+ {
+ return true;
+ }
+ if (res == UrlParseResult::Fail)
{
return false;
}
it++;
}
- return true;
+ return it == end;
}
} // namespace details