Line data Source code
1 : /*
2 : ___________________________________________
3 : | _ ___ _ |
4 : | | | |__ \ | | |
5 : | | |__ ) |__ _ __ _ ___ _ __ | |_ |
6 : | | '_ \ / // _` |/ _` |/ _ \ '_ \| __| | HTTP/2 AGENT FOR MOCK TESTING
7 : | | | | |/ /| (_| | (_| | __/ | | | |_ | Version 0.0.z
8 : | |_| |_|____\__,_|\__, |\___|_| |_|\__| | https://github.com/testillano/h2agent
9 : | __/ | |
10 : | |___/ |
11 : |___________________________________________|
12 :
13 : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14 : SPDX-License-Identifier: MIT
15 : Copyright (c) 2021 Eduardo Ramos
16 :
17 : Permission is hereby granted, free of charge, to any person obtaining a copy
18 : of this software and associated documentation files (the "Software"), to deal
19 : in the Software without restriction, including without limitation the rights
20 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 : copies of the Software, and to permit persons to whom the Software is
22 : furnished to do so, subject to the following conditions:
23 :
24 : The above copyright notice and this permission notice shall be included in all
25 : copies or substantial portions of the Software.
26 :
27 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 : SOFTWARE.
34 : */
35 :
36 : #include <string>
37 : #include <regex>
38 :
39 : #include <nlohmann/json.hpp>
40 :
41 : #include <ert/tracing/Logger.hpp>
42 :
43 : #include <AdminServerMatchingData.hpp>
44 :
45 : namespace h2agent
46 : {
47 : namespace model
48 : {
49 :
50 307 : AdminServerMatchingData::AdminServerMatchingData() {
51 307 : auto cfg = std::make_shared<Config>();
52 307 : cfg->json["algorithm"] = "FullMatching";
53 307 : std::atomic_store(&config_, std::shared_ptr<const Config>(std::move(cfg)));
54 :
55 307 : server_matching_schema_.setJson(h2agent::adminSchemas::server_matching); // won't fail
56 307 : }
57 :
58 194 : AdminServerMatchingData::LoadResult AdminServerMatchingData::load(const nlohmann::json &j) {
59 :
60 194 : std::string error{};
61 194 : if (!server_matching_schema_.validate(j, error)) {
62 5 : return BadSchema;
63 : }
64 :
65 : // Build new immutable config on the side (no lock held)
66 189 : auto cfg = std::make_shared<Config>();
67 189 : cfg->json = j;
68 :
69 : // Mandatory
70 189 : auto algorithm_it = j.find("algorithm");
71 :
72 : // Optional
73 189 : bool hasRgx = false;
74 189 : bool hasFmt = false;
75 189 : auto rgx_it = j.find("rgx");
76 189 : if (rgx_it != j.end() && rgx_it->is_string()) {
77 6 : hasRgx = true;
78 : try {
79 7 : cfg->rgx.assign(rgx_it->get<std::string>(), std::regex::optimize);
80 : }
81 1 : catch (std::regex_error &e) {
82 1 : ert::tracing::Logger::error(e.what(), ERT_FILE_LOCATION);
83 1 : return BadContent;
84 1 : }
85 : }
86 :
87 188 : auto fmt_it = j.find("fmt");
88 188 : if (fmt_it != j.end() && fmt_it->is_string()) {
89 4 : hasFmt = true;
90 4 : cfg->fmt = *fmt_it;
91 : }
92 :
93 188 : auto uriPathQueryParameters_it = j.find("uriPathQueryParameters");
94 188 : if (uriPathQueryParameters_it != j.end()) {
95 4 : auto filter_it = (*uriPathQueryParameters_it).find("filter"); // mandatory
96 4 : if (filter_it->is_string()) {
97 4 : if (*filter_it == "Sort") {
98 2 : cfg->uri_path_query_parameters_filter = Sort;
99 : }
100 2 : else if (*filter_it == "PassBy") {
101 1 : cfg->uri_path_query_parameters_filter = PassBy;
102 : }
103 1 : else if (*filter_it == "Ignore") {
104 1 : cfg->uri_path_query_parameters_filter = Ignore;
105 : }
106 : }
107 :
108 4 : auto separator_it = (*uriPathQueryParameters_it).find("separator"); // optional
109 4 : if (separator_it != (*uriPathQueryParameters_it).end() && separator_it->is_string()) {
110 2 : if (*separator_it == "Ampersand") {
111 1 : cfg->uri_path_query_parameters_separator = Ampersand;
112 : }
113 1 : else if (*separator_it == "Semicolon") {
114 1 : cfg->uri_path_query_parameters_separator = Semicolon;
115 : }
116 : }
117 : }
118 :
119 : // Checkings
120 188 : if (*algorithm_it == "FullMatching") {
121 176 : if (hasRgx || hasFmt) {
122 3 : ert::tracing::Logger::error("FullMatching does not allow rgx and/or fmt fields", ERT_FILE_LOCATION);
123 3 : return BadContent;
124 : }
125 173 : cfg->algorithm = FullMatching;
126 : }
127 12 : else if (*algorithm_it == "FullMatchingRegexReplace") {
128 3 : if (!hasRgx || !hasFmt) {
129 1 : ert::tracing::Logger::error("FullMatchingRegexReplace requires rgx and fmt fields", ERT_FILE_LOCATION);
130 1 : return BadContent;
131 : }
132 2 : cfg->algorithm = FullMatchingRegexReplace;
133 : }
134 9 : else if (*algorithm_it == "RegexMatching") {
135 9 : if (hasRgx || hasFmt) {
136 2 : ert::tracing::Logger::error("RegexMatching does not allow rgx and/or fmt fields", ERT_FILE_LOCATION);
137 2 : return BadContent;
138 : }
139 7 : cfg->algorithm = RegexMatching;
140 : }
141 :
142 : // Atomic swap — traffic threads holding the old shared_ptr are safe
143 182 : std::atomic_store(&config_, std::shared_ptr<const Config>(std::move(cfg)));
144 :
145 182 : return Success;
146 194 : }
147 :
148 : }
149 : }
150 :
|