-
Notifications
You must be signed in to change notification settings - Fork 4
handle in path params #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| #include <optional> | ||
| #include <ostream> | ||
| #include <ranges> | ||
|
|
||
| #include "utl/enumerate.h" | ||
|
|
||
|
|
@@ -108,7 +109,7 @@ std::string_view to_cpp(type const t) { | |
|
|
||
| struct indent { | ||
| explicit indent(int indent, char separator = ',') | ||
| : indent_{indent}, separator_{separator} {} | ||
| : separator_{separator}, indent_{indent} {} | ||
|
|
||
| void operator()(std::ostream& out) { | ||
| if (!first_ && separator_ != '\0') { | ||
|
|
@@ -314,10 +315,37 @@ void gen_member_init(YAML::Node const& root, | |
| out << ", allow_missing)}"; | ||
| } | ||
|
|
||
| void gen_member_init_from_seg(YAML::Node const& root, | ||
| YAML::Node const& x, | ||
| std::size_t idx, | ||
| std::ostream& out) { | ||
| auto const schema = x["schema"]; | ||
| auto const name = x["name"].as<std::string_view>(); | ||
| auto const type = get_type(root, name, schema, true); | ||
| out << " " << name << "_{::openapi::parse_segment<" << type << ">(segs, \"" | ||
| << name << "\", " << idx << ")}"; | ||
| } | ||
|
|
||
| void write_params(YAML::Node const& root, | ||
| YAML::Node const& path, | ||
| YAML::Node const& n, | ||
| std::ostream& header, | ||
| std::ostream& source) { | ||
| const auto p = path.as<std::string_view>(); | ||
| auto segs = p | std::views::split('/'); | ||
|
DIDONAX marked this conversation as resolved.
Outdated
|
||
| auto seg_idx = std::unordered_map<std::string_view, std::size_t>{}; | ||
|
|
||
| for (auto const& [i, seg] : segs | std::views::enumerate) { | ||
| auto sv = std::string_view{seg.begin(), seg.end()}; | ||
| if (sv.starts_with('{')) { | ||
| sv.remove_prefix(1); | ||
| } | ||
| if (sv.ends_with('}')) { | ||
| sv.remove_suffix(1); | ||
| } | ||
| seg_idx.emplace(sv, i - 1); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 0 - 1 underflows?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ?? |
||
| } | ||
|
|
||
| for (auto const& p : n["parameters"]) { | ||
| auto const name = p["name"].as<std::string_view>(); | ||
| auto const items = p["schema"]["items"]; | ||
|
|
@@ -333,20 +361,27 @@ void write_params(YAML::Node const& root, | |
| header << "struct " << id << " {\n"; | ||
| header << " explicit " << id << "();\n"; | ||
| header << " explicit " << id | ||
| << "(boost::urls::params_view const&, bool allow_missing = false);\n"; | ||
| << "(boost::urls::params_view const&, boost::urls::segments_view " | ||
| "const& = {}, bool allow_missing = false);\n"; | ||
| header << " boost::urls::url to_url(std::string_view path) const;\n"; | ||
|
|
||
| source << id << "::" << id << "() = default;\n"; | ||
| source << id << "::" << id | ||
| << "(boost::urls::params_view const& params, bool allow_missing)"; | ||
| << "(boost::urls::params_view const& params, " | ||
| "boost::urls::segments_view const& segs, bool allow_missing)"; | ||
|
|
||
| auto const parameters = n["parameters"]; | ||
| if (parameters.IsDefined() && parameters.size() != 0) { | ||
| source << " :"; | ||
| auto ind = indent{2}; | ||
| for (auto const& p : parameters) { | ||
| ind(source); | ||
| gen_member_init(root, p, is_required(p), source); | ||
| if (p["in"].IsDefined() && p["in"].as<std::string_view>() == "path") { | ||
| auto const idx = seg_idx.at(p["name"].as<std::string_view>()); | ||
| gen_member_init_from_seg(root, p, idx, source); | ||
| } else { | ||
| gen_member_init(root, p, is_required(p), source); | ||
| } | ||
| } | ||
| } | ||
| source << "\n {}\n\n"; | ||
|
|
@@ -357,6 +392,9 @@ void write_params(YAML::Node const& root, | |
| source << " auto u = boost::urls::url{path};\n"; | ||
| source << " auto default_val = " << id << "{};\n"; | ||
| for (auto const& p : parameters) { | ||
| if (p["in"].IsDefined() && p["in"].as<std::string_view>() == "path") { | ||
| continue; | ||
| } | ||
| auto const name = p["name"].as<std::string_view>(); | ||
| auto const schema = p["schema"]; | ||
| auto const has_default = schema["default"].IsDefined(); | ||
|
|
@@ -402,7 +440,9 @@ void write_params(YAML::Node const& root, | |
|
|
||
| for (auto const& p : n["parameters"]) { | ||
| auto const name = p["name"].as<std::string_view>(); | ||
| gen_member(root, name, is_required(p), p["schema"], header); | ||
| auto const in_path = | ||
| p["in"].IsDefined() && p["in"].as<std::string_view>() == "path"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. don't repeat yourself - write a utility function
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ?? |
||
| gen_member(root, name, in_path || is_required(p), p["schema"], header); | ||
| } | ||
| header << "};\n\n"; | ||
| } | ||
|
|
@@ -560,7 +600,7 @@ void write_types(YAML::Node const& root, | |
|
|
||
| for (auto const& path : root["paths"]) { | ||
| for (auto const& method : path.second) { | ||
| write_params(root, method.second, header, source); | ||
| write_params(root, path.first, method.second, header, source); | ||
|
|
||
| for (auto const& response : method.second["responses"]) { | ||
| gen_type(method.second["operationId"].as<std::string>() + "_response", | ||
|
|
@@ -573,4 +613,4 @@ void write_types(YAML::Node const& root, | |
| write_postlude(header, source, ns); | ||
| } | ||
|
|
||
| } // namespace openapi | ||
| } // namespace openapi | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| #include "gtest/gtest.h" | ||
|
|
||
| #include "openapi/bad_request_exception.h" | ||
|
DIDONAX marked this conversation as resolved.
Outdated
|
||
| #include "yaml-cpp/yaml.h" | ||
|
|
||
| #include "cista/hash.h" | ||
|
|
||
| #include "boost/json.hpp" | ||
| #include "boost/url.hpp" | ||
|
|
||
| #include "utl/verify.h" | ||
|
|
||
| #include "openapi/gen_types.h" | ||
| #include "openapi/json.h" | ||
|
|
||
| #include "pet-api/pet-api.h" | ||
|
|
||
| using namespace openapi; | ||
| using namespace pet; | ||
|
|
||
| TEST(openapi, valid_query) { | ||
| auto url = boost::urls::url_view{"/items/test/42?param3=10"}; | ||
| auto p = pet::getItems_params{url.params(), url.segments()}; | ||
| EXPECT_EQ("test", p.param1_); | ||
| EXPECT_EQ(42, p.param2_); | ||
| EXPECT_EQ(10, p.param3_); | ||
| } | ||
|
|
||
| TEST(openapi, path_params_always_required) { | ||
| auto url = boost::urls::url_view{"/items?param3=10"}; | ||
| EXPECT_THROW(pet::getItems_params(url.params(), url.segments()), | ||
| openapi::bad_request_exception); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.