couchbase 4.4.2 → 4.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. package/CMakeLists.txt +2 -0
  2. package/deps/couchbase-cxx-client/CMakeLists.txt +17 -14
  3. package/deps/couchbase-cxx-client/README.md +2 -2
  4. package/deps/couchbase-cxx-client/cmake/Packaging.cmake +4 -0
  5. package/deps/couchbase-cxx-client/cmake/Testing.cmake +1 -1
  6. package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +24 -2
  7. package/deps/couchbase-cxx-client/cmake/couchbase-cxx-client.spec.in +43 -4
  8. package/deps/couchbase-cxx-client/core/agent_group.cxx +8 -0
  9. package/deps/couchbase-cxx-client/core/agent_group.hxx +4 -0
  10. package/deps/couchbase-cxx-client/core/bucket.cxx +16 -20
  11. package/deps/couchbase-cxx-client/core/bucket.hxx +12 -12
  12. package/deps/couchbase-cxx-client/core/cluster.cxx +44 -52
  13. package/deps/couchbase-cxx-client/core/cluster_agent.cxx +8 -0
  14. package/deps/couchbase-cxx-client/core/cluster_agent.hxx +4 -0
  15. package/deps/couchbase-cxx-client/core/collections_component.cxx +2 -2
  16. package/deps/couchbase-cxx-client/core/columnar/agent.cxx +2 -2
  17. package/deps/couchbase-cxx-client/core/columnar/agent.hxx +1 -1
  18. package/deps/couchbase-cxx-client/core/columnar/management_component.cxx +3 -3
  19. package/deps/couchbase-cxx-client/core/columnar/query_component.cxx +103 -45
  20. package/deps/couchbase-cxx-client/core/columnar/query_component.hxx +1 -0
  21. package/deps/couchbase-cxx-client/core/free_form_http_request.hxx +8 -0
  22. package/deps/couchbase-cxx-client/core/http_component.cxx +55 -24
  23. package/deps/couchbase-cxx-client/core/http_component.hxx +4 -0
  24. package/deps/couchbase-cxx-client/core/impl/analytics_index_manager.cxx +15 -15
  25. package/deps/couchbase-cxx-client/core/impl/bootstrap_error.hxx +10 -2
  26. package/deps/couchbase-cxx-client/core/impl/bucket.cxx +1 -1
  27. package/deps/couchbase-cxx-client/core/impl/bucket_manager.cxx +6 -6
  28. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +36 -40
  29. package/deps/couchbase-cxx-client/core/impl/collection.cxx +2 -2
  30. package/deps/couchbase-cxx-client/core/impl/collection_manager.cxx +5 -5
  31. package/deps/couchbase-cxx-client/core/impl/observe_poll.cxx +13 -5
  32. package/deps/couchbase-cxx-client/core/impl/observe_poll.hxx +1 -3
  33. package/deps/couchbase-cxx-client/core/impl/query_index_manager.cxx +6 -6
  34. package/deps/couchbase-cxx-client/core/impl/scan_result.cxx +1 -1
  35. package/deps/couchbase-cxx-client/core/impl/search_index_manager.cxx +12 -12
  36. package/deps/couchbase-cxx-client/core/io/http_command.hxx +31 -20
  37. package/deps/couchbase-cxx-client/core/io/http_session.cxx +5 -0
  38. package/deps/couchbase-cxx-client/core/io/http_session.hxx +17 -4
  39. package/deps/couchbase-cxx-client/core/io/http_session_manager.hxx +97 -49
  40. package/deps/couchbase-cxx-client/core/io/mcbp_command.hxx +15 -14
  41. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +48 -33
  42. package/deps/couchbase-cxx-client/core/io/streams.cxx +256 -0
  43. package/deps/couchbase-cxx-client/core/io/streams.hxx +31 -155
  44. package/deps/couchbase-cxx-client/core/logger/configuration.hxx +5 -0
  45. package/deps/couchbase-cxx-client/core/logger/custom_rotating_file_sink.cxx +2 -3
  46. package/deps/couchbase-cxx-client/core/logger/logger.cxx +39 -7
  47. package/deps/couchbase-cxx-client/core/logger/logger.hxx +7 -0
  48. package/deps/couchbase-cxx-client/core/metrics/meter_wrapper.cxx +188 -0
  49. package/deps/couchbase-cxx-client/core/metrics/meter_wrapper.hxx +73 -0
  50. package/deps/couchbase-cxx-client/core/operations/management/bucket_describe.cxx +2 -1
  51. package/deps/couchbase-cxx-client/core/operations/management/bucket_drop.cxx +3 -1
  52. package/deps/couchbase-cxx-client/core/operations/management/bucket_flush.cxx +3 -1
  53. package/deps/couchbase-cxx-client/core/operations/management/bucket_get.cxx +3 -1
  54. package/deps/couchbase-cxx-client/core/operations/management/bucket_update.cxx +3 -1
  55. package/deps/couchbase-cxx-client/core/operations/management/collection_create.cxx +3 -2
  56. package/deps/couchbase-cxx-client/core/operations/management/collection_drop.cxx +5 -2
  57. package/deps/couchbase-cxx-client/core/operations/management/collection_update.cxx +4 -2
  58. package/deps/couchbase-cxx-client/core/operations/management/group_upsert.cxx +3 -3
  59. package/deps/couchbase-cxx-client/core/operations/management/scope_create.cxx +2 -1
  60. package/deps/couchbase-cxx-client/core/operations/management/scope_drop.cxx +4 -1
  61. package/deps/couchbase-cxx-client/core/operations/management/scope_get_all.cxx +3 -1
  62. package/deps/couchbase-cxx-client/core/operations/management/search_index_analyze_document.cxx +3 -2
  63. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_ingest.cxx +3 -2
  64. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_plan_freeze.cxx +3 -2
  65. package/deps/couchbase-cxx-client/core/operations/management/search_index_control_query.cxx +3 -2
  66. package/deps/couchbase-cxx-client/core/operations/management/search_index_drop.cxx +5 -2
  67. package/deps/couchbase-cxx-client/core/operations/management/search_index_get.cxx +5 -2
  68. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_all.cxx +4 -2
  69. package/deps/couchbase-cxx-client/core/operations/management/search_index_get_documents_count.cxx +3 -2
  70. package/deps/couchbase-cxx-client/core/operations/management/search_index_upsert.cxx +5 -2
  71. package/deps/couchbase-cxx-client/core/operations/management/view_index_drop.cxx +2 -1
  72. package/deps/couchbase-cxx-client/core/operations/management/view_index_get.cxx +2 -1
  73. package/deps/couchbase-cxx-client/core/operations/management/view_index_get_all.cxx +3 -1
  74. package/deps/couchbase-cxx-client/core/operations/management/view_index_upsert.cxx +2 -1
  75. package/deps/couchbase-cxx-client/core/origin.cxx +37 -17
  76. package/deps/couchbase-cxx-client/core/platform/base64.cc +1 -1
  77. package/deps/couchbase-cxx-client/core/platform/random.cc +2 -0
  78. package/deps/couchbase-cxx-client/core/platform/uuid.h +6 -6
  79. package/deps/couchbase-cxx-client/core/row_streamer.cxx +1 -1
  80. package/deps/couchbase-cxx-client/core/sasl/scram-sha/stringutils.cc +1 -1
  81. package/deps/couchbase-cxx-client/core/sasl/scram-sha/stringutils.h +4 -4
  82. package/deps/couchbase-cxx-client/core/topology/configuration.hxx +2 -0
  83. package/deps/couchbase-cxx-client/core/topology/configuration_json.hxx +8 -0
  84. package/deps/couchbase-cxx-client/core/tracing/constants.hxx +3 -0
  85. package/deps/couchbase-cxx-client/core/tracing/tracer_wrapper.cxx +87 -0
  86. package/deps/couchbase-cxx-client/core/tracing/tracer_wrapper.hxx +57 -0
  87. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +16 -15
  88. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +2 -2
  89. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +2 -2
  90. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +2 -2
  91. package/deps/couchbase-cxx-client/core/utils/connection_string.cxx +128 -52
  92. package/deps/couchbase-cxx-client/couchbase/analytics_options.hxx +4 -3
  93. package/deps/couchbase-cxx-client/couchbase/codec/tao_json_serializer.hxx +1 -1
  94. package/deps/couchbase-cxx-client/couchbase/mutate_in_specs.hxx +2 -2
  95. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +4 -3
  96. package/deps/couchbase-cxx-client/couchbase/search_options.hxx +1 -1
  97. package/package.json +8 -8
  98. package/src/binding.cpp +13 -13
@@ -0,0 +1,188 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2024. Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include "meter_wrapper.hxx"
19
+
20
+ #include <couchbase/error_codes.hxx>
21
+
22
+ #include <mutex>
23
+ #include <system_error>
24
+
25
+ namespace couchbase::core::metrics
26
+ {
27
+ namespace
28
+ {
29
+ auto
30
+ snake_case_to_camel_case(const std::string& s) -> std::string
31
+ {
32
+ std::string res{};
33
+ bool capitalize{ true }; // First letter should be capitalized
34
+ for (const char c : s) {
35
+ if (c == '_') {
36
+ capitalize = true; // Next letter should be capitalized
37
+ continue;
38
+ }
39
+ if (capitalize) {
40
+ res += static_cast<char>(std::toupper(c));
41
+ capitalize = false;
42
+ } else {
43
+ res += c;
44
+ }
45
+ }
46
+ return res;
47
+ }
48
+
49
+ auto
50
+ extract_error_name(std::error_code ec) -> std::string
51
+ {
52
+ const std::string::size_type pos = ec.message().find(' ');
53
+ if (pos != std::string::npos) {
54
+ return ec.message().substr(0, pos);
55
+ }
56
+ return ec.message();
57
+ }
58
+
59
+ auto
60
+ service_to_string(service_type s) -> std::string
61
+ {
62
+ switch (s) {
63
+ case service_type::analytics:
64
+ return "analytics";
65
+ case service_type::search:
66
+ return "search";
67
+ case service_type::key_value:
68
+ return "kv";
69
+ case service_type::management:
70
+ return "management";
71
+ case service_type::eventing:
72
+ return "eventing";
73
+ case service_type::query:
74
+ return "query";
75
+ case service_type::view:
76
+ return "views";
77
+ }
78
+ return {};
79
+ }
80
+
81
+ auto
82
+ get_standardized_outcome(std::error_code ec) -> std::string
83
+ {
84
+ if (!ec) {
85
+ return "Success";
86
+ }
87
+
88
+ // SDK-specific errors
89
+ if (ec.value() >= 1000) {
90
+ return "CouchbaseError";
91
+ }
92
+
93
+ // Errors where message and RFC-message don't match
94
+ if (ec == errc::field_level_encryption::generic_cryptography_failure) {
95
+ return "CryptoError";
96
+ }
97
+
98
+ return snake_case_to_camel_case(extract_error_name(ec));
99
+ }
100
+ } // namespace
101
+
102
+ auto
103
+ metric_attributes::encode() const -> std::map<std::string, std::string>
104
+ {
105
+ std::map<std::string, std::string> tags = { { "db.couchbase.service",
106
+ service_to_string(service) },
107
+ { "db.operation", operation },
108
+ { "outcome", get_standardized_outcome(ec) } };
109
+
110
+ if (internal.cluster_name.has_value()) {
111
+ tags.emplace("db.couchbase.cluster_name", internal.cluster_name.value());
112
+ }
113
+ if (internal.cluster_uuid.has_value()) {
114
+ tags.emplace("db.couchbase.cluster_uuid", internal.cluster_uuid.value());
115
+ }
116
+ if (bucket_name) {
117
+ tags.emplace("db.name", bucket_name.value());
118
+ }
119
+ if (scope_name) {
120
+ tags.emplace("db.couchbase.scope", scope_name.value());
121
+ }
122
+ if (collection_name) {
123
+ tags.emplace("db.couchbase.collection", collection_name.value());
124
+ }
125
+
126
+ return tags;
127
+ }
128
+
129
+ meter_wrapper::meter_wrapper(std::shared_ptr<couchbase::metrics::meter> meter)
130
+ : meter_{ std::move(meter) }
131
+ {
132
+ }
133
+
134
+ void
135
+ meter_wrapper::start()
136
+ {
137
+ meter_->start();
138
+ }
139
+
140
+ void
141
+ meter_wrapper::stop()
142
+ {
143
+ meter_->stop();
144
+ }
145
+
146
+ void
147
+ meter_wrapper::record_value(metric_attributes attrs,
148
+ std::chrono::steady_clock::time_point start_time)
149
+ {
150
+ static const std::string meter_name{ "db.couchbase.operations" };
151
+
152
+ {
153
+ const std::shared_lock lock{ cluster_labels_mutex_ };
154
+
155
+ if (cluster_name_) {
156
+ attrs.internal.cluster_name = cluster_name_;
157
+ }
158
+ if (cluster_uuid_) {
159
+ attrs.internal.cluster_uuid = cluster_uuid_;
160
+ }
161
+ }
162
+
163
+ auto tags = attrs.encode();
164
+ meter_->get_value_recorder(meter_name, tags)
165
+ ->record_value(std::chrono::duration_cast<std::chrono::microseconds>(
166
+ std::chrono::steady_clock::now() - start_time)
167
+ .count());
168
+ }
169
+
170
+ void
171
+ meter_wrapper::update_config(topology::configuration config)
172
+ {
173
+ const std::scoped_lock<std::shared_mutex> lock{ cluster_labels_mutex_ };
174
+ if (config.cluster_uuid.has_value()) {
175
+ cluster_uuid_ = config.cluster_uuid;
176
+ }
177
+ if (config.cluster_name.has_value()) {
178
+ cluster_name_ = config.cluster_name;
179
+ }
180
+ }
181
+
182
+ auto
183
+ meter_wrapper::create(std::shared_ptr<couchbase::metrics::meter> meter)
184
+ -> std::shared_ptr<meter_wrapper>
185
+ {
186
+ return std::make_shared<meter_wrapper>(std::move(meter));
187
+ }
188
+ } // namespace couchbase::core::metrics
@@ -0,0 +1,73 @@
1
+ /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2024. Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #pragma once
19
+
20
+ #include "core/config_listener.hxx"
21
+ #include "core/service_type.hxx"
22
+ #include "core/topology/configuration.hxx"
23
+
24
+ #include <couchbase/metrics/meter.hxx>
25
+
26
+ #include <chrono>
27
+ #include <map>
28
+ #include <optional>
29
+ #include <shared_mutex>
30
+ #include <string>
31
+ #include <system_error>
32
+
33
+ namespace couchbase::core::metrics
34
+ {
35
+ struct metric_attributes {
36
+ couchbase::core::service_type service;
37
+ std::string operation;
38
+ std::error_code ec;
39
+ std::optional<std::string> bucket_name{};
40
+ std::optional<std::string> scope_name{};
41
+ std::optional<std::string> collection_name{};
42
+
43
+ struct {
44
+ std::optional<std::string> cluster_name{};
45
+ std::optional<std::string> cluster_uuid{};
46
+ } internal{};
47
+
48
+ [[nodiscard]] auto encode() const -> std::map<std::string, std::string>;
49
+ };
50
+
51
+ class meter_wrapper : public config_listener
52
+ {
53
+ public:
54
+ explicit meter_wrapper(std::shared_ptr<couchbase::metrics::meter> meter);
55
+
56
+ void start();
57
+ void stop();
58
+
59
+ void record_value(metric_attributes attrs, std::chrono::steady_clock::time_point start_time);
60
+
61
+ void update_config(topology::configuration config) override;
62
+
63
+ [[nodiscard]] static auto create(std::shared_ptr<couchbase::metrics::meter> meter)
64
+ -> std::shared_ptr<meter_wrapper>;
65
+
66
+ private:
67
+ std::shared_ptr<couchbase::metrics::meter> meter_;
68
+
69
+ std::optional<std::string> cluster_name_{};
70
+ std::optional<std::string> cluster_uuid_{};
71
+ std::shared_mutex cluster_labels_mutex_{};
72
+ };
73
+ } // namespace couchbase::core::metrics
@@ -18,6 +18,7 @@
18
18
  #include "bucket_describe.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -33,7 +34,7 @@ bucket_describe_request::encode_to(encoded_request_type& encoded,
33
34
  http_context& /* context */) const -> std::error_code
34
35
  {
35
36
  encoded.method = "GET";
36
- encoded.path = fmt::format("/pools/default/b/{}", name);
37
+ encoded.path = fmt::format("/pools/default/b/{}", utils::string_codec::v2::path_escape(name));
37
38
  return {};
38
39
  }
39
40
 
@@ -17,6 +17,7 @@
17
17
 
18
18
  #include "bucket_drop.hxx"
19
19
 
20
+ #include "core/utils/url_codec.hxx"
20
21
  #include "error_utils.hxx"
21
22
 
22
23
  #include <fmt/core.h>
@@ -28,7 +29,8 @@ bucket_drop_request::encode_to(encoded_request_type& encoded,
28
29
  http_context& /* context */) const -> std::error_code
29
30
  {
30
31
  encoded.method = "DELETE";
31
- encoded.path = fmt::format("/pools/default/buckets/{}", name);
32
+ encoded.path =
33
+ fmt::format("/pools/default/buckets/{}", utils::string_codec::v2::path_escape(name));
32
34
  return {};
33
35
  }
34
36
 
@@ -17,6 +17,7 @@
17
17
 
18
18
  #include "bucket_flush.hxx"
19
19
 
20
+ #include "core/utils/url_codec.hxx"
20
21
  #include "error_utils.hxx"
21
22
 
22
23
  #include <fmt/core.h>
@@ -28,7 +29,8 @@ bucket_flush_request::encode_to(encoded_request_type& encoded,
28
29
  http_context& /* context */) const -> std::error_code
29
30
  {
30
31
  encoded.method = "POST";
31
- encoded.path = fmt::format("/pools/default/buckets/{}/controller/doFlush", name);
32
+ encoded.path = fmt::format("/pools/default/buckets/{}/controller/doFlush",
33
+ utils::string_codec::v2::path_escape(name));
32
34
  return {};
33
35
  }
34
36
 
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "core/management/bucket_settings_json.hxx"
21
21
  #include "core/utils/json.hxx"
22
+ #include "core/utils/url_codec.hxx"
22
23
  #include "error_utils.hxx"
23
24
 
24
25
  #include <fmt/core.h>
@@ -31,7 +32,8 @@ bucket_get_request::encode_to(encoded_request_type& encoded,
31
32
  http_context& /* context */) const -> std::error_code
32
33
  {
33
34
  encoded.method = "GET";
34
- encoded.path = fmt::format("/pools/default/buckets/{}", name);
35
+ encoded.path =
36
+ fmt::format("/pools/default/buckets/{}", utils::string_codec::v2::path_escape(name));
35
37
  return {};
36
38
  }
37
39
 
@@ -20,6 +20,7 @@
20
20
  #include "core/management/bucket_settings.hxx"
21
21
  #include "core/utils/join_strings.hxx"
22
22
  #include "core/utils/json.hxx"
23
+ #include "core/utils/url_codec.hxx"
23
24
  #include "error_utils.hxx"
24
25
 
25
26
  #include <couchbase/durability_level.hxx>
@@ -33,7 +34,8 @@ bucket_update_request::encode_to(encoded_request_type& encoded,
33
34
  http_context& /* context */) const -> std::error_code
34
35
  {
35
36
  encoded.method = "POST";
36
- encoded.path = fmt::format("/pools/default/buckets/{}", bucket.name);
37
+ encoded.path =
38
+ fmt::format("/pools/default/buckets/{}", utils::string_codec::v2::path_escape(bucket.name));
37
39
 
38
40
  encoded.headers["content-type"] = "application/x-www-form-urlencoded";
39
41
 
@@ -33,8 +33,9 @@ collection_create_request::encode_to(encoded_request_type& encoded,
33
33
  http_context& /*context*/) const -> std::error_code
34
34
  {
35
35
  encoded.method = "POST";
36
- encoded.path =
37
- fmt::format("/pools/default/buckets/{}/scopes/{}/collections", bucket_name, scope_name);
36
+ encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}/collections",
37
+ utils::string_codec::v2::path_escape(bucket_name),
38
+ utils::string_codec::v2::path_escape(scope_name));
38
39
  encoded.headers["content-type"] = "application/x-www-form-urlencoded";
39
40
  encoded.body = fmt::format("name={}", utils::string_codec::form_encode(collection_name));
40
41
  if (max_expiry) {
@@ -18,6 +18,7 @@
18
18
  #include "collection_drop.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -32,8 +33,10 @@ collection_drop_request::encode_to(encoded_request_type& encoded,
32
33
  http_context& /* context */) const -> std::error_code
33
34
  {
34
35
  encoded.method = "DELETE";
35
- encoded.path = fmt::format(
36
- "/pools/default/buckets/{}/scopes/{}/collections/{}", bucket_name, scope_name, collection_name);
36
+ encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}/collections/{}",
37
+ utils::string_codec::v2::path_escape(bucket_name),
38
+ utils::string_codec::v2::path_escape(scope_name),
39
+ utils::string_codec::v2::path_escape(collection_name));
37
40
  return {};
38
41
  }
39
42
 
@@ -33,8 +33,10 @@ collection_update_request::encode_to(encoded_request_type& encoded,
33
33
  http_context& /*context*/) const -> std::error_code
34
34
  {
35
35
  encoded.method = "PATCH";
36
- encoded.path = fmt::format(
37
- "/pools/default/buckets/{}/scopes/{}/collections/{}", bucket_name, scope_name, collection_name);
36
+ encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}/collections/{}",
37
+ utils::string_codec::v2::path_escape(bucket_name),
38
+ utils::string_codec::v2::path_escape(scope_name),
39
+ utils::string_codec::v2::path_escape(collection_name));
38
40
  encoded.headers["content-type"] = "application/x-www-form-urlencoded";
39
41
  std::map<std::string, std::string> values{};
40
42
  if (max_expiry.has_value()) {
@@ -46,11 +46,11 @@ group_upsert_request::encode_to(encoded_request_type& encoded,
46
46
  for (const auto& role : group.roles) {
47
47
  std::string spec = role.name;
48
48
  if (role.bucket) {
49
- spec += fmt::format("[{}", role.bucket.value());
49
+ spec += fmt::format("[{}", utils::string_codec::v2::path_escape(role.bucket.value()));
50
50
  if (role.scope) {
51
- spec += fmt::format(":{}", role.scope.value());
51
+ spec += fmt::format(":{}", utils::string_codec::v2::path_escape(role.scope.value()));
52
52
  if (role.collection) {
53
- spec += fmt::format(":{}", role.collection.value());
53
+ spec += fmt::format(":{}", utils::string_codec::v2::path_escape(role.collection.value()));
54
54
  }
55
55
  }
56
56
  spec += "]";
@@ -33,7 +33,8 @@ scope_create_request::encode_to(encoded_request_type& encoded,
33
33
  http_context& /* context */) const -> std::error_code
34
34
  {
35
35
  encoded.method = "POST";
36
- encoded.path = fmt::format("/pools/default/buckets/{}/scopes", bucket_name);
36
+ encoded.path = fmt::format("/pools/default/buckets/{}/scopes",
37
+ utils::string_codec::v2::path_escape(bucket_name));
37
38
  encoded.headers["content-type"] = "application/x-www-form-urlencoded";
38
39
  encoded.body = fmt::format("name={}", utils::string_codec::form_encode(scope_name));
39
40
  return {};
@@ -18,6 +18,7 @@
18
18
  #include "scope_drop.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -32,7 +33,9 @@ scope_drop_request::encode_to(encoded_request_type& encoded,
32
33
  http_context& /* context */) const -> std::error_code
33
34
  {
34
35
  encoded.method = "DELETE";
35
- encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}", bucket_name, scope_name);
36
+ encoded.path = fmt::format("/pools/default/buckets/{}/scopes/{}",
37
+ utils::string_codec::v2::path_escape(bucket_name),
38
+ utils::string_codec::v2::path_escape(scope_name));
36
39
  return {};
37
40
  }
38
41
 
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "core/topology/collections_manifest_json.hxx"
21
21
  #include "core/utils/json.hxx"
22
+ #include "core/utils/url_codec.hxx"
22
23
  #include "error_utils.hxx"
23
24
 
24
25
  #include <fmt/core.h>
@@ -31,7 +32,8 @@ scope_get_all_request::encode_to(encoded_request_type& encoded,
31
32
  http_context& /* context */) const -> std::error_code
32
33
  {
33
34
  encoded.method = "GET";
34
- encoded.path = fmt::format("/pools/default/buckets/{}/scopes", bucket_name);
35
+ encoded.path = fmt::format("/pools/default/buckets/{}/scopes",
36
+ utils::string_codec::v2::path_escape(bucket_name));
35
37
  return {};
36
38
  }
37
39
 
@@ -18,6 +18,7 @@
18
18
  #include "search_index_analyze_document.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -38,8 +39,8 @@ search_index_analyze_document_request::encode_to(encoded_request_type& encoded,
38
39
  encoded.headers["content-type"] = "application/json";
39
40
  if (bucket_name.has_value() && scope_name.has_value()) {
40
41
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/analyzeDoc",
41
- bucket_name.value(),
42
- scope_name.value(),
42
+ utils::string_codec::v2::path_escape(bucket_name.value()),
43
+ utils::string_codec::v2::path_escape(scope_name.value()),
43
44
  index_name);
44
45
  } else {
45
46
  encoded.path = fmt::format("/api/index/{}/analyzeDoc", index_name);
@@ -18,6 +18,7 @@
18
18
  #include "search_index_control_ingest.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -35,8 +36,8 @@ search_index_control_ingest_request::encode_to(encoded_request_type& encoded,
35
36
  encoded.method = "POST";
36
37
  if (bucket_name.has_value() && scope_name.has_value()) {
37
38
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/ingestControl/{}",
38
- bucket_name.value(),
39
- scope_name.value(),
39
+ utils::string_codec::v2::path_escape(bucket_name.value()),
40
+ utils::string_codec::v2::path_escape(scope_name.value()),
40
41
  index_name,
41
42
  pause ? "pause" : "resume");
42
43
  } else {
@@ -18,6 +18,7 @@
18
18
  #include "search_index_control_plan_freeze.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -36,8 +37,8 @@ search_index_control_plan_freeze_request::encode_to(encoded_request_type& encode
36
37
  encoded.method = "POST";
37
38
  if (bucket_name.has_value() && scope_name.has_value()) {
38
39
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/planFreezeControl/{}",
39
- bucket_name.value(),
40
- scope_name.value(),
40
+ utils::string_codec::v2::path_escape(bucket_name.value()),
41
+ utils::string_codec::v2::path_escape(scope_name.value()),
41
42
  index_name,
42
43
  freeze ? "freeze" : "unfreeze");
43
44
  } else {
@@ -18,6 +18,7 @@
18
18
  #include "search_index_control_query.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -35,8 +36,8 @@ search_index_control_query_request::encode_to(encoded_request_type& encoded,
35
36
  encoded.method = "POST";
36
37
  if (bucket_name.has_value() && scope_name.has_value()) {
37
38
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/queryControl/{}",
38
- bucket_name.value(),
39
- scope_name.value(),
39
+ utils::string_codec::v2::path_escape(bucket_name.value()),
40
+ utils::string_codec::v2::path_escape(scope_name.value()),
40
41
  index_name,
41
42
  allow ? "allow" : "disallow");
42
43
  } else {
@@ -18,6 +18,7 @@
18
18
  #include "search_index_drop.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -34,8 +35,10 @@ search_index_drop_request::encode_to(encoded_request_type& encoded,
34
35
  }
35
36
  encoded.method = "DELETE";
36
37
  if (bucket_name.has_value() && scope_name.has_value()) {
37
- encoded.path = fmt::format(
38
- "/api/bucket/{}/scope/{}/index/{}", bucket_name.value(), scope_name.value(), index_name);
38
+ encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}",
39
+ utils::string_codec::v2::path_escape(bucket_name.value()),
40
+ utils::string_codec::v2::path_escape(scope_name.value()),
41
+ index_name);
39
42
  } else {
40
43
  encoded.path = fmt::format("/api/index/{}", index_name);
41
44
  }
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "core/management/search_index_json.hxx"
21
21
  #include "core/utils/json.hxx"
22
+ #include "core/utils/url_codec.hxx"
22
23
  #include "error_utils.hxx"
23
24
 
24
25
  #include <fmt/core.h>
@@ -35,8 +36,10 @@ search_index_get_request::encode_to(encoded_request_type& encoded,
35
36
  }
36
37
  encoded.method = "GET";
37
38
  if (bucket_name.has_value() && scope_name.has_value()) {
38
- encoded.path = fmt::format(
39
- "/api/bucket/{}/scope/{}/index/{}", bucket_name.value(), scope_name.value(), index_name);
39
+ encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}",
40
+ utils::string_codec::v2::path_escape(bucket_name.value()),
41
+ utils::string_codec::v2::path_escape(scope_name.value()),
42
+ index_name);
40
43
  } else {
41
44
  encoded.path = fmt::format("/api/index/{}", index_name);
42
45
  }
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "core/management/search_index_json.hxx"
21
21
  #include "core/utils/json.hxx"
22
+ #include "core/utils/url_codec.hxx"
22
23
  #include "error_utils.hxx"
23
24
 
24
25
  #include <fmt/core.h>
@@ -32,8 +33,9 @@ search_index_get_all_request::encode_to(encoded_request_type& encoded,
32
33
  {
33
34
  encoded.method = "GET";
34
35
  if (bucket_name.has_value() && scope_name.has_value()) {
35
- encoded.path =
36
- fmt::format("/api/bucket/{}/scope/{}/index", bucket_name.value(), scope_name.value());
36
+ encoded.path = fmt::format("/api/bucket/{}/scope/{}/index",
37
+ utils::string_codec::v2::path_escape(bucket_name.value()),
38
+ utils::string_codec::v2::path_escape(scope_name.value()));
37
39
  } else {
38
40
  encoded.path = "/api/index";
39
41
  }
@@ -18,6 +18,7 @@
18
18
  #include "search_index_get_documents_count.hxx"
19
19
 
20
20
  #include "core/utils/json.hxx"
21
+ #include "core/utils/url_codec.hxx"
21
22
  #include "error_utils.hxx"
22
23
 
23
24
  #include <fmt/core.h>
@@ -33,8 +34,8 @@ search_index_get_documents_count_request::encode_to(encoded_request_type& encode
33
34
  encoded.method = "GET";
34
35
  if (bucket_name.has_value() && scope_name.has_value()) {
35
36
  encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}/count",
36
- bucket_name.value(),
37
- scope_name.value(),
37
+ utils::string_codec::v2::path_escape(bucket_name.value()),
38
+ utils::string_codec::v2::path_escape(scope_name.value()),
38
39
  index_name);
39
40
  } else {
40
41
  encoded.path = fmt::format("/api/index/{}/count", index_name);
@@ -19,6 +19,7 @@
19
19
 
20
20
  #include "core/management/search_index_json.hxx"
21
21
  #include "core/utils/json.hxx"
22
+ #include "core/utils/url_codec.hxx"
22
23
  #include "error_utils.hxx"
23
24
 
24
25
  #include <fmt/core.h>
@@ -37,8 +38,10 @@ search_index_upsert_request::encode_to(encoded_request_type& encoded,
37
38
  encoded.headers["cache-control"] = "no-cache";
38
39
  encoded.headers["content-type"] = "application/json";
39
40
  if (bucket_name.has_value() && scope_name.has_value()) {
40
- encoded.path = fmt::format(
41
- "/api/bucket/{}/scope/{}/index/{}", bucket_name.value(), scope_name.value(), index.name);
41
+ encoded.path = fmt::format("/api/bucket/{}/scope/{}/index/{}",
42
+ utils::string_codec::v2::path_escape(bucket_name.value()),
43
+ utils::string_codec::v2::path_escape(scope_name.value()),
44
+ index.name);
42
45
  } else {
43
46
  encoded.path = fmt::format("/api/index/{}", index.name);
44
47
  }