mirror of
https://github.com/kernelkit/infix.git
synced 2026-07-22 01:13:00 +02:00
197 lines
8.5 KiB
Diff
197 lines
8.5 KiB
Diff
From 97ceef119c900c37bbaa27860c3b43cfa6d69f95 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Pecka?= <tomas.pecka@cesnet.cz>
|
|
Date: Mon, 13 Jan 2025 13:01:07 +0100
|
|
Subject: [PATCH 27/44] restconf: refactor uri parser for stream URIs
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
Organization: Wires
|
|
|
|
This is a preparation for the upcoming patch that will add support for
|
|
subscribed streams. I will use boost spirit x3 parser to parse such
|
|
URIs so I need to refactor the existing parser, which is not really a
|
|
parser, but we only match for the two known URIs.
|
|
|
|
Change-Id: Ib76973cd967fc3e9558ceb6be8f51239ce4c5ef3
|
|
Signed-off-by: Mattias Walström <lazzer@gmail.com>
|
|
---
|
|
src/restconf/Server.cpp | 15 +--------------
|
|
src/restconf/uri.cpp | 36 +++++++++++++++++++++++++++---------
|
|
src/restconf/uri.h | 11 ++++++-----
|
|
src/restconf/uri_impl.h | 2 ++
|
|
tests/uri-parser.cpp | 4 ++--
|
|
5 files changed, 38 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/src/restconf/Server.cpp b/src/restconf/Server.cpp
|
|
index daf23ed..d356f7e 100644
|
|
--- a/src/restconf/Server.cpp
|
|
+++ b/src/restconf/Server.cpp
|
|
@@ -874,7 +874,6 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std::
|
|
|
|
server->handle(netconfStreamRoot, [this, conn](const auto& req, const auto& res) mutable {
|
|
auto sess = conn.sessionStart();
|
|
- libyang::DataFormat dataFormat;
|
|
std::optional<std::string> xpathFilter;
|
|
std::optional<sysrepo::NotificationTimeStamp> startTime;
|
|
std::optional<sysrepo::NotificationTimeStamp> stopTime;
|
|
@@ -890,18 +889,6 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std::
|
|
|
|
auto streamRequest = asRestconfStreamRequest(req.method(), req.uri().path, req.uri().raw_query);
|
|
|
|
- switch(streamRequest.type) {
|
|
- case RestconfStreamRequest::Type::NetconfNotificationJSON:
|
|
- dataFormat = libyang::DataFormat::JSON;
|
|
- break;
|
|
- case RestconfStreamRequest::Type::NetconfNotificationXML:
|
|
- dataFormat = libyang::DataFormat::XML;
|
|
- break;
|
|
- default:
|
|
- // GCC 14 complains about uninitialized variable, but asRestconfStreamRequest() would have thrown
|
|
- __builtin_unreachable();
|
|
- }
|
|
-
|
|
if (auto it = streamRequest.queryParams.find("filter"); it != streamRequest.queryParams.end()) {
|
|
xpathFilter = std::get<std::string>(it->second);
|
|
}
|
|
@@ -916,7 +903,7 @@ Server::Server(sysrepo::Connection conn, const std::string& address, const std::
|
|
// The signal is constructed outside NotificationStream class because it is required to be passed to
|
|
// NotificationStream's parent (EventStream) constructor where it already must be constructed
|
|
// Yes, this is a hack.
|
|
- auto client = std::make_shared<NotificationStream>(req, res, std::make_shared<rousette::http::EventStream::Signal>(), sess, dataFormat, xpathFilter, startTime, stopTime);
|
|
+ auto client = std::make_shared<NotificationStream>(req, res, std::make_shared<rousette::http::EventStream::Signal>(), sess, streamRequest.type.encoding, xpathFilter, startTime, stopTime);
|
|
client->activate();
|
|
} catch (const auth::Error& e) {
|
|
processAuthError(req, res, e, [&res]() {
|
|
diff --git a/src/restconf/uri.cpp b/src/restconf/uri.cpp
|
|
index da1e3a5..e95d70e 100644
|
|
--- a/src/restconf/uri.cpp
|
|
+++ b/src/restconf/uri.cpp
|
|
@@ -57,6 +57,13 @@ const auto resources = x3::rule<class resources, URIPath>{"resources"} =
|
|
((x3::lit("/") | x3::eps) /* /restconf/ and /restconf */ >> x3::attr(URIPrefix{URIPrefix::Type::RestconfRoot}) >> x3::attr(std::vector<PathSegment>{}));
|
|
const auto uriGrammar = x3::rule<class grammar, URIPath>{"grammar"} = x3::lit("/restconf") >> resources;
|
|
|
|
+
|
|
+const auto netconfStream = x3::rule<class netconfStream, RestconfStreamRequest::NetconfStream>{"netconfStream"} =
|
|
+ x3::lit("/NETCONF") >>
|
|
+ ((x3::lit("/XML") >> x3::attr(libyang::DataFormat::XML)) |
|
|
+ (x3::lit("/JSON") >> x3::attr(libyang::DataFormat::JSON)));
|
|
+const auto streamUriGrammar = x3::rule<class grammar, RestconfStreamRequest::NetconfStream>{"streamsGrammar"} = x3::lit("/streams") >> netconfStream;
|
|
+
|
|
// clang-format on
|
|
}
|
|
|
|
@@ -197,6 +204,17 @@ std::optional<queryParams::QueryParams> parseQueryParams(const std::string& quer
|
|
return ret;
|
|
}
|
|
|
|
+std::optional<RestconfStreamRequest::NetconfStream> parseStreamUri(const std::string& uriPath)
|
|
+{
|
|
+ std::optional<RestconfStreamRequest::NetconfStream> ret;
|
|
+
|
|
+ if (!x3::parse(std::begin(uriPath), std::end(uriPath), streamUriGrammar >> x3::eoi, ret)) {
|
|
+ return std::nullopt;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
URIPrefix::URIPrefix()
|
|
: resourceType(URIPrefix::Type::BasicRestconfData)
|
|
{
|
|
@@ -637,20 +655,20 @@ std::optional<std::variant<libyang::Module, libyang::SubmoduleParsed>> asYangMod
|
|
return std::nullopt;
|
|
}
|
|
|
|
-RestconfStreamRequest asRestconfStreamRequest(const std::string& httpMethod, const std::string& uriPath, const std::string& uriQueryString)
|
|
+RestconfStreamRequest::NetconfStream::NetconfStream() = default;
|
|
+RestconfStreamRequest::NetconfStream::NetconfStream(const libyang::DataFormat& encoding)
|
|
+ : encoding(encoding)
|
|
{
|
|
- static const auto netconfStreamRoot = "/streams/NETCONF/";
|
|
- RestconfStreamRequest::Type type;
|
|
+}
|
|
|
|
+RestconfStreamRequest asRestconfStreamRequest(const std::string& httpMethod, const std::string& uriPath, const std::string& uriQueryString)
|
|
+{
|
|
if (httpMethod != "GET" && httpMethod != "HEAD") {
|
|
throw ErrorResponse(405, "application", "operation-not-supported", "Method not allowed.");
|
|
}
|
|
|
|
- if (uriPath == netconfStreamRoot + "XML"s) {
|
|
- type = RestconfStreamRequest::Type::NetconfNotificationXML;
|
|
- } else if (uriPath == netconfStreamRoot + "JSON"s) {
|
|
- type = RestconfStreamRequest::Type::NetconfNotificationJSON;
|
|
- } else {
|
|
+ auto type = impl::parseStreamUri(uriPath);
|
|
+ if (!type) {
|
|
throw ErrorResponse(404, "application", "invalid-value", "Invalid stream");
|
|
}
|
|
|
|
@@ -661,7 +679,7 @@ RestconfStreamRequest asRestconfStreamRequest(const std::string& httpMethod, con
|
|
|
|
validateQueryParametersForStream(*queryParameters);
|
|
|
|
- return {type, *queryParameters};
|
|
+ return {*type, *queryParameters};
|
|
}
|
|
|
|
/** @brief Returns a set of allowed HTTP methods for given URI. Usable for the 'allow' header */
|
|
diff --git a/src/restconf/uri.h b/src/restconf/uri.h
|
|
index f6df724..6f1f69f 100644
|
|
--- a/src/restconf/uri.h
|
|
+++ b/src/restconf/uri.h
|
|
@@ -197,11 +197,12 @@ struct RestconfRequest {
|
|
};
|
|
|
|
struct RestconfStreamRequest {
|
|
- enum class Type {
|
|
- NetconfNotificationJSON,
|
|
- NetconfNotificationXML,
|
|
- };
|
|
- Type type;
|
|
+ struct NetconfStream {
|
|
+ libyang::DataFormat encoding;
|
|
+
|
|
+ NetconfStream();
|
|
+ NetconfStream(const libyang::DataFormat& encoding);
|
|
+ } type;
|
|
queryParams::QueryParams queryParams;
|
|
};
|
|
|
|
diff --git a/src/restconf/uri_impl.h b/src/restconf/uri_impl.h
|
|
index 2bcdb3f..00b22f6 100644
|
|
--- a/src/restconf/uri_impl.h
|
|
+++ b/src/restconf/uri_impl.h
|
|
@@ -66,6 +66,8 @@ BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::impl::YangModule, name, revision);
|
|
BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::PathSegment, apiIdent, keys);
|
|
BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::ApiIdentifier, prefix, identifier);
|
|
|
|
+BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::RestconfStreamRequest::NetconfStream, encoding);
|
|
+
|
|
BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::queryParams::fields::ParenExpr, lhs, rhs);
|
|
BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::queryParams::fields::SlashExpr, lhs, rhs);
|
|
BOOST_FUSION_ADAPT_STRUCT(rousette::restconf::queryParams::fields::SemiExpr, lhs, rhs);
|
|
diff --git a/tests/uri-parser.cpp b/tests/uri-parser.cpp
|
|
index fd5dd8b..53d1fbb 100644
|
|
--- a/tests/uri-parser.cpp
|
|
+++ b/tests/uri-parser.cpp
|
|
@@ -1072,13 +1072,13 @@ TEST_CASE("URI path parser")
|
|
|
|
{
|
|
auto [type, queryParams] = asRestconfStreamRequest("GET", "/streams/NETCONF/XML", "");
|
|
- REQUIRE(type == RestconfStreamRequest::Type::NetconfNotificationXML);
|
|
+ REQUIRE(type.encoding == libyang::DataFormat::XML);
|
|
REQUIRE(queryParams.empty());
|
|
}
|
|
|
|
{
|
|
auto [type, queryParams] = asRestconfStreamRequest("GET", "/streams/NETCONF/JSON", "");
|
|
- REQUIRE(type == RestconfStreamRequest::Type::NetconfNotificationJSON);
|
|
+ REQUIRE(type.encoding == libyang::DataFormat::JSON);
|
|
REQUIRE(queryParams.empty());
|
|
}
|
|
|
|
--
|
|
2.43.0
|
|
|