diff options
author | Ed Tanous <edtanous@google.com> | 2022-08-19 17:00:38 +0300 |
---|---|---|
committer | Ed Tanous <edtanous@google.com> | 2022-08-24 00:47:32 +0300 |
commit | 7f8d8fa938f521d18278e9cb5673bacd83217d09 (patch) | |
tree | 5134ef203f9db67ce142c18fbc23bc22899697ef /http/utility.hpp | |
parent | a3526fee27da0e324cd022ea77d282d1146b3317 (diff) | |
download | bmcweb-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.hpp | 47 |
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 |