Skip to content

Commit 3cead04

Browse files
committed
Method mapping: Added support to map HTTP methods
1 parent fba9e05 commit 3cead04

4 files changed

Lines changed: 57 additions & 8 deletions

File tree

include/oas_validator.hpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <exception>
1919
#include <string>
2020
#include <unordered_map>
21+
#include <unordered_set>
2122

2223
class ValidatorInitExc; ///< Forward declaration for the custom exception class.
2324
class OASValidatorImp; ///< Forward declaration for the implementation class.
@@ -56,13 +57,29 @@ class OASValidator
5657

5758
public:
5859
/**
59-
* @brief Constructor that takes the path to the OAS specification file.
60+
* @brief Constructor that takes the path to the OAS specification file and an optional method mapping.
61+
*
6062
* @param oas_specs File path to the OAS specification in JSON format or JSON string containing the OAS
6163
* specification.
6264
*
63-
* @note The OAS specification can be provided as a file path or as a JSON string.
65+
* @param method_map An optional unordered_map where each key is an HTTP method and the value is an unordered_set
66+
* of methods that can be treated as the key method. This allows certain HTTP methods to be treated as others.
67+
*
68+
* For example:
69+
* @code
70+
* std::unordered_map<std::string, std::unordered_set<std::string>> method_map = {
71+
* {"OPTIONS", {"GET", "POST", "PUT", "DELETE", "HEAD", "PATCH"}},
72+
* {"HEAD", {"GET"}} // Treat HEAD request as GET
73+
* };
74+
* OASValidator validator(oas_specs, method_map);
75+
* @endcode
76+
*
77+
* @note The OAS specification can be provided as a file path or as a JSON string. If the method map is provided,
78+
* it allows certain HTTP methods to be treated as others. For instance, with the mapping {"HEAD", {"GET"}},
79+
* a HEAD request can be validated as the GET request, if HEAD method is not defined.
6480
*/
65-
explicit OASValidator(const std::string& oas_specs);
81+
explicit OASValidator(const std::string& oas_specs,
82+
const std::unordered_map<std::string, std::unordered_set<std::string>>& method_map = {});
6683

6784
/**
6885
* @brief Copy constructor.

include/oas_validator_imp.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
class OASValidatorImp
1616
{
1717
public:
18-
explicit OASValidatorImp(const std::string& oas_specs);
18+
explicit OASValidatorImp(const std::string& oas_specs,
19+
const std::unordered_map<std::string, std::unordered_set<std::string>>& method_map = {});
1920
ValidationError ValidateRoute(const std::string& method, const std::string& http_path, std::string& error_msg);
2021
ValidationError ValidateBody(const std::string& method, const std::string& http_path, const std::string& json_body,
2122
std::string& error_msg);
@@ -45,9 +46,14 @@ class OASValidatorImp
4546
PathTrie path_trie{};
4647
};
4748

49+
const std::unordered_map<std::string, std::unordered_set<std::string>> method_map_;
4850
std::array<PerMethod, static_cast<size_t>(HttpMethod::COUNT)> oas_validators_{};
4951
MethodValidator method_validator_{};
5052

53+
ValidationError GetValidators(const std::string& method, const std::string& mapped_method,
54+
const std::string& http_path, ValidatorsStore*& validators, std::string& error_msg,
55+
std::unordered_map<size_t, ParamRange>* param_idxs = nullptr,
56+
std::string* query = nullptr);
5157
ValidationError GetValidators(const std::string& method, const std::string& http_path, ValidatorsStore*& validators,
5258
std::string& error_msg, std::unordered_map<size_t, ParamRange>* param_idxs = nullptr,
5359
std::string* query = nullptr);

src/oas_validator.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88

99
#include "oas_validator_imp.hpp"
1010

11-
OASValidator::OASValidator(const std::string& oas_specs)
12-
: impl_(new OASValidatorImp(oas_specs))
11+
OASValidator::OASValidator(const std::string& oas_specs,
12+
const std::unordered_map<std::string, std::unordered_set<std::string>>& method_map)
13+
: impl_(new OASValidatorImp(oas_specs, method_map))
1314
{
1415
}
1516

src/oas_validator_imp.cpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include <rapidjson/istreamwrapper.h>
1010
#include <sstream>
1111

12-
OASValidatorImp::OASValidatorImp(const std::string& oas_specs)
12+
OASValidatorImp::OASValidatorImp(const std::string& oas_specs,
13+
const std::unordered_map<std::string, std::unordered_set<std::string>>& method_map)
14+
: method_map_(method_map)
1315
{
1416
rapidjson::Document doc;
1517
ParseSpecs(oas_specs, doc);
@@ -175,7 +177,30 @@ ValidationError OASValidatorImp::GetValidators(const std::string& method, const
175177
auto err_code = method_validator_.Validate(method, error_msg);
176178
CHECK_ERROR(err_code)
177179

178-
auto enum_method = kStringToMethod.at(method);
180+
err_code = GetValidators(method, method, http_path, validators, error_msg, param_idxs, query);
181+
if (ValidationError::INVALID_ROUTE == err_code) {
182+
try {
183+
auto mapped_methods = method_map_.at(method);
184+
for (const auto& mapped_method : mapped_methods) {
185+
err_code = GetValidators(method, mapped_method, http_path, validators, error_msg, param_idxs, query);
186+
if (ValidationError::NONE == err_code) {
187+
return err_code;
188+
}
189+
}
190+
} catch (const std::out_of_range&) {
191+
return err_code;
192+
}
193+
}
194+
195+
return err_code;
196+
}
197+
198+
ValidationError OASValidatorImp::GetValidators(const std::string& method, const std::string& mapped_method,
199+
const std::string& http_path, ValidatorsStore*& validators,
200+
std::string& error_msg,
201+
std::unordered_map<size_t, ParamRange>* param_idxs, std::string* query)
202+
{
203+
auto enum_method = kStringToMethod.at(mapped_method);
179204

180205
auto query_pos = http_path.find('?');
181206
if (std::string::npos != query_pos && query) {

0 commit comments

Comments
 (0)