From ce3edd2bef34f95d590f30bdb1a86c0cc0b6665b Mon Sep 17 00:00:00 2001 From: Amaury Chamayou Date: Fri, 13 Dec 2024 15:26:52 +0000 Subject: [PATCH] Expose ccf::http::parse_accept_header() --- CHANGELOG.md | 8 ++++ doc/build_apps/api.rst | 10 +++++ {src/http => include/ccf}/http_accept.h | 4 +- {src/node/rpc => include/ccf}/rpc_exception.h | 0 python/pyproject.toml | 2 +- src/endpoints/json_handler.cpp | 6 +-- src/http/test/http_test.cpp | 38 ++++++++++--------- src/node/rpc/frontend.h | 2 +- 8 files changed, 46 insertions(+), 24 deletions(-) rename {src/http => include/ccf}/http_accept.h (98%) rename {src/node/rpc => include/ccf}/rpc_exception.h (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index cacaf51495ae..ff44bc169f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). +## [6.0.0-dev10] + +[6.0.0-dev10]: https://github.com/microsoft/CCF/releases/tag/6.0.0-dev10 + +### Added + +- Expose `ccf:http::parse_accept_header()` and `ccf::http::AcceptHeaderField`. + ## [6.0.0-dev9] [6.0.0-dev9]: https://github.com/microsoft/CCF/releases/tag/6.0.0-dev9 diff --git a/doc/build_apps/api.rst b/doc/build_apps/api.rst index 0ec3229e031f..1c8bd610e6a6 100644 --- a/doc/build_apps/api.rst +++ b/doc/build_apps/api.rst @@ -166,6 +166,16 @@ HTTP Entity Tags Matching :project: CCF :members: +HTTP Accept Header Matching +--------------------------- + +.. doxygenstruct:: ccf::http::AcceptHeaderField + :project: CCF + :members: + +.. doxygenfunction:: ccf::http::parse_accept_header + :project: CCF + COSE ---- diff --git a/src/http/http_accept.h b/include/ccf/http_accept.h similarity index 98% rename from src/http/http_accept.h rename to include/ccf/http_accept.h index f460b350d0fc..89961b5e7ffe 100644 --- a/src/http/http_accept.h +++ b/include/ccf/http_accept.h @@ -5,11 +5,11 @@ #include "ccf/ds/nonstd.h" #include "ccf/http_status.h" #include "ccf/odata_error.h" -#include "node/rpc/rpc_exception.h" +#include "ccf/rpc_exception.h" #include -namespace http +namespace ccf::http { struct AcceptHeaderField { diff --git a/src/node/rpc/rpc_exception.h b/include/ccf/rpc_exception.h similarity index 100% rename from src/node/rpc/rpc_exception.h rename to include/ccf/rpc_exception.h diff --git a/python/pyproject.toml b/python/pyproject.toml index ad1ed8b74c50..23f9707e1cd9 100644 --- a/python/pyproject.toml +++ b/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "ccf" -version = "6.0.0-dev9" +version = "6.0.0-dev10" authors = [ { name="CCF Team", email="CCF-Sec@microsoft.com" }, ] diff --git a/src/endpoints/json_handler.cpp b/src/endpoints/json_handler.cpp index f8cdc1fa54fa..599e512f9f40 100644 --- a/src/endpoints/json_handler.cpp +++ b/src/endpoints/json_handler.cpp @@ -3,12 +3,12 @@ #include "ccf/json_handler.h" #include "ccf/ds/logger.h" +#include "ccf/http_accept.h" #include "ccf/http_consts.h" #include "ccf/odata_error.h" #include "ccf/redirect.h" #include "ccf/rpc_context.h" -#include "http/http_accept.h" -#include "node/rpc/rpc_exception.h" +#include "ccf/rpc_exception.h" #include @@ -64,7 +64,7 @@ namespace ccf if (accept_it.has_value()) { const auto accept_options = - ::http::parse_accept_header(accept_it.value()); + ccf::http::parse_accept_header(accept_it.value()); bool matched = false; for (const auto& option : accept_options) { diff --git a/src/http/test/http_test.cpp b/src/http/test/http_test.cpp index b4280a8a753c..de7e8ce14e04 100644 --- a/src/http/test/http_test.cpp +++ b/src/http/test/http_test.cpp @@ -2,8 +2,8 @@ // Licensed under the Apache 2.0 License. #include "ccf/crypto/key_pair.h" +#include "ccf/http_accept.h" #include "ccf/http_query.h" -#include "http/http_accept.h" #include "http/http_builder.h" #include "http/http_parser.h" @@ -565,12 +565,12 @@ DOCTEST_TEST_CASE("Query parser") DOCTEST_TEST_CASE("Parse Accept header") { { - const auto fields = http::parse_accept_header(""); + const auto fields = ccf::http::parse_accept_header(""); DOCTEST_REQUIRE(fields.empty()); } { - const auto fields = http::parse_accept_header("foo/bar;q=0.25"); + const auto fields = ccf::http::parse_accept_header("foo/bar;q=0.25"); DOCTEST_REQUIRE(fields.size() == 1); const auto& field = fields[0]; DOCTEST_REQUIRE(field.mime_type == "foo"); @@ -581,7 +581,7 @@ DOCTEST_TEST_CASE("Parse Accept header") { // Shuffled and modified version of Firefox 91 default value, to test // sorting - const auto fields = http::parse_accept_header( + const auto fields = ccf::http::parse_accept_header( "image/webp;q=0.8, " "image/*;q=0.8, " "text/html, " @@ -591,31 +591,35 @@ DOCTEST_TEST_CASE("Parse Accept header") "*/*;q=0.8"); DOCTEST_REQUIRE(fields.size() == 7); - DOCTEST_REQUIRE(fields[0] == http::AcceptHeaderField{"text", "html", 1.0f}); DOCTEST_REQUIRE( - fields[1] == http::AcceptHeaderField{"image", "avif", 1.0f}); + fields[0] == ccf::http::AcceptHeaderField{"text", "html", 1.0f}); DOCTEST_REQUIRE( - fields[2] == http::AcceptHeaderField{"application", "xhtml+xml", 1.0f}); + fields[1] == ccf::http::AcceptHeaderField{"image", "avif", 1.0f}); DOCTEST_REQUIRE( - fields[3] == http::AcceptHeaderField{"application", "xml", 0.9f}); + fields[2] == + ccf::http::AcceptHeaderField{"application", "xhtml+xml", 1.0f}); DOCTEST_REQUIRE( - fields[4] == http::AcceptHeaderField{"image", "webp", 0.8f}); - DOCTEST_REQUIRE(fields[5] == http::AcceptHeaderField{"image", "*", 0.8f}); - DOCTEST_REQUIRE(fields[6] == http::AcceptHeaderField{"*", "*", 0.8f}); + fields[3] == ccf::http::AcceptHeaderField{"application", "xml", 0.9f}); + DOCTEST_REQUIRE( + fields[4] == ccf::http::AcceptHeaderField{"image", "webp", 0.8f}); + DOCTEST_REQUIRE( + fields[5] == ccf::http::AcceptHeaderField{"image", "*", 0.8f}); + DOCTEST_REQUIRE(fields[6] == ccf::http::AcceptHeaderField{"*", "*", 0.8f}); } { - DOCTEST_REQUIRE_THROWS(http::parse_accept_header("not_a_mime_type")); - DOCTEST_REQUIRE_THROWS(http::parse_accept_header("valid/mime;q=notnum")); - DOCTEST_REQUIRE_THROWS(http::parse_accept_header(",")); + DOCTEST_REQUIRE_THROWS(ccf::http::parse_accept_header("not_a_mime_type")); + DOCTEST_REQUIRE_THROWS( + ccf::http::parse_accept_header("valid/mime;q=notnum")); + DOCTEST_REQUIRE_THROWS(ccf::http::parse_accept_header(",")); } } DOCTEST_TEST_CASE("Accept header MIME matching") { - const auto a = http::AcceptHeaderField{"foo", "bar", 1.0f}; - const auto b = http::AcceptHeaderField{"foo", "*", 1.0f}; - const auto c = http::AcceptHeaderField{"*", "*", 1.0f}; + const auto a = ccf::http::AcceptHeaderField{"foo", "bar", 1.0f}; + const auto b = ccf::http::AcceptHeaderField{"foo", "*", 1.0f}; + const auto c = ccf::http::AcceptHeaderField{"*", "*", 1.0f}; DOCTEST_REQUIRE(a.matches("foo/bar")); DOCTEST_REQUIRE_FALSE(a.matches("foo/baz")); diff --git a/src/node/rpc/frontend.h b/src/node/rpc/frontend.h index bb3f7847a29c..67064d98073c 100644 --- a/src/node/rpc/frontend.h +++ b/src/node/rpc/frontend.h @@ -6,6 +6,7 @@ #include "ccf/http_status.h" #include "ccf/node_context.h" #include "ccf/pal/locking.h" +#include "ccf/rpc_exception.h" #include "ccf/service/node_info_network.h" #include "ccf/service/signed_req.h" #include "ccf/service/tables/jwt.h" @@ -20,7 +21,6 @@ #include "kv/store.h" #include "node/endpoint_context_impl.h" #include "node/node_configuration_subsystem.h" -#include "rpc_exception.h" #include "service/internal_tables_access.h" #define FMT_HEADER_ONLY