Skip to content

Commit 983f9cf

Browse files
authored
Applied changes to percent encoding of query parameters in the uri_builder (#126)
* Applied changes to percent encoding of query parameters in the uri_builder * Applied feedback from review * Updated API of uri_builder and encoding functions
1 parent 2c57190 commit 983f9cf

File tree

8 files changed

+164
-112
lines changed

8 files changed

+164
-112
lines changed

include/network/uri/detail/encode.hpp

-18
Original file line numberDiff line numberDiff line change
@@ -105,17 +105,6 @@ OutputIterator encode_path(InputIterator first, InputIterator last,
105105
return out;
106106
}
107107

108-
template <typename InputIterator, typename OutputIterator>
109-
OutputIterator encode_query(InputIterator first, InputIterator last,
110-
OutputIterator out) {
111-
auto it = first;
112-
while (it != last) {
113-
detail::encode_char(*it, out, "/.@&%;=");
114-
++it;
115-
}
116-
return out;
117-
}
118-
119108
template <typename InputIterator, typename OutputIterator>
120109
OutputIterator encode_query_component(InputIterator first, InputIterator last,
121110
OutputIterator out) {
@@ -167,13 +156,6 @@ String encode_path(const String &path) {
167156
return encoded;
168157
}
169158

170-
template <class String>
171-
String encode_query(const String &query) {
172-
String encoded;
173-
encode_query(std::begin(query), std::end(query), std::back_inserter(encoded));
174-
return encoded;
175-
}
176-
177159
template <class String>
178160
String encode_fragment(const String &fragment) {
179161
String encoded;

include/network/uri/uri.hpp

+43-3
Original file line numberDiff line numberDiff line change
@@ -547,20 +547,60 @@ class uri {
547547
}
548548

549549
/**
550-
* \brief Encodes a sequence according to the rules for encoding a
551-
* query part.
550+
* \deprecated Avoid using this function
551+
* \brief Equivalent to \c encode_query_component
552552
* \param first The iterator at first element in the input
553553
* sequence.
554554
* \param last The iterator at end + 1th element in the input
555555
* sequence.
556556
* \param out The iterator at the first element in the output
557557
* sequence.
558558
* \returns The iterator at the end + 1th in the output sequence.
559+
* \sa encode_query_commponent
560+
* \sa encode_query_key_value_pair
559561
*/
560562
template <typename InputIter, typename OutputIter>
561563
static OutputIter encode_query(InputIter first, InputIter last,
562564
OutputIter out) {
563-
return detail::encode_query(first, last, out);
565+
return encode_query_component(first, last, out);
566+
}
567+
568+
/**
569+
* \brief Encodes a sequence according to the rules for encoding a
570+
* query component, including the '=' character.
571+
* \param first The iterator at first element in the input
572+
* sequence.
573+
* \param last The iterator at end + 1th element in the input
574+
* sequence.
575+
* \param out The iterator at the first element in the output
576+
* sequence.
577+
* \returns The iterator at the end + 1th in the output sequence.
578+
*/
579+
template <typename InputIter, typename OutputIter>
580+
static OutputIter encode_query_component(
581+
InputIter first, InputIter last, OutputIter out) {
582+
return detail::encode_query_component(first, last, out);
583+
}
584+
585+
/**
586+
* \brief Encodes a sequence according to the rules for encoding a
587+
* query key value pair.
588+
* \param key_first The iterator at first element in the input
589+
* sequence.
590+
* \param key_last The iterator at end + 1th element in the input
591+
* sequence.
592+
* \param out The iterator at the first element in the output
593+
* sequence.
594+
* \returns The iterator at the end + 1th in the output sequence.
595+
*/
596+
template <typename InputIter, typename OutputIter>
597+
static OutputIter encode_query_key_value_pair(
598+
InputIter key_first, InputIter key_last,
599+
InputIter value_first, InputIter value_last,
600+
OutputIter out) {
601+
out = detail::encode_query_component(key_first, key_last, out);
602+
out++ = '=';
603+
return detail::encode_query_component(value_first, value_last, out);
564604
}
565605

566606
/**

include/network/uri/uri_builder.hpp

+31-15
Original file line numberDiff line numberDiff line change
@@ -182,26 +182,36 @@ class uri_builder {
182182
uri_builder &clear_path();
183183

184184
/**
185+
* \deprecated Use append_query_component
186+
* \warning This function's behaviour has changed and percent encoding
187+
* of the '=' character is not ignored.
185188
* \brief Adds a new query to the uri_builder.
186189
* \param query The query.
187190
* \returns \c *this
191+
* \sa append_query_parameter
188192
*/
189193
template <typename Source>
190194
uri_builder &append_query(const Source &query) {
191-
append_query(detail::translate(query));
192-
return *this;
195+
return append_query_component(query);
193196
}
194197

195198
/**
196-
* \brief Clears the URI query part.
199+
* \brief Appends a new query component to the uri_builder. The
200+
* '=' symbol is percent encoded.
201+
* \param component The query component.
197202
* \returns \c *this
203+
* \sa append_query_key_value_pair
198204
*/
199-
uri_builder &clear_query();
205+
template <typename Source>
206+
uri_builder &append_query_component(const Source &component) {
207+
append_query_component(detail::translate(component));
208+
return *this;
209+
}
200210

201211
/**
202212
* \brief Adds a new query key/value pair to the uri_builder.
203-
* \param key The query key.
204-
* \param value The query value.
213+
* \param key The query parameter key.
214+
* \param value The query parameter value.
205215
* \returns \c *this
206216
*/
207217
template <typename Key, typename Value>
@@ -211,6 +221,12 @@ class uri_builder {
211221
return *this;
212222
}
213223

224+
/**
225+
* \brief Clears the URI query part.
226+
* \returns \c *this
227+
*/
228+
uri_builder &clear_query();
229+
214230
/**
215231
* \brief Adds a new fragment to the uri_builder.
216232
* \param fragment The fragment.
@@ -239,15 +255,15 @@ class uri_builder {
239255
network::uri uri() const;
240256

241257
private:
242-
void set_scheme(string_type scheme);
243-
void set_user_info(string_type user_info);
244-
void set_host(string_type host);
245-
void set_port(string_type port);
246-
void set_authority(string_type authority);
247-
void set_path(string_type path);
248-
void append_query(string_type query);
249-
void append_query_key_value_pair(string_type key, string_type value);
250-
void set_fragment(string_type fragment);
258+
void set_scheme(string_type &&scheme);
259+
void set_user_info(string_type &&user_info);
260+
void set_host(string_type &&host);
261+
void set_port(string_type &&port);
262+
void set_authority(string_type &&authority);
263+
void set_path(string_type &&path);
264+
void append_query_component(string_type &&name);
265+
void append_query_key_value_pair(string_type &&key, string_type &&value);
266+
void set_fragment(string_type &&fragment);
251267

252268
optional<string_type> scheme_, user_info_, host_, port_, path_, query_,
253269
fragment_;

src/uri.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,7 @@ uri::query_iterator::query_iterator(optional<detail::uri_part> query)
275275

276276
uri::query_iterator::query_iterator(const query_iterator &other)
277277
: query_(other.query_)
278-
, kvp_(other.kvp_) {
279-
280-
}
278+
, kvp_(other.kvp_) {}
281279

282280
uri::query_iterator &uri::query_iterator::operator = (const query_iterator &other) {
283281
auto tmp(other);

src/uri_builder.cpp

+22-23
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,46 @@
1212
namespace network {
1313
uri_builder::uri_builder(const network::uri &base_uri) {
1414
if (base_uri.has_scheme()) {
15-
set_scheme(base_uri.scheme().to_string());
15+
scheme_ = base_uri.scheme().to_string();
1616
}
1717

1818
if (base_uri.has_user_info()) {
19-
set_user_info(base_uri.user_info().to_string());
19+
user_info_ = base_uri.user_info().to_string();
2020
}
2121

2222
if (base_uri.has_host()) {
23-
set_host(base_uri.host().to_string());
23+
host_ = base_uri.host().to_string();
2424
}
2525

2626
if (base_uri.has_port()) {
27-
set_port(base_uri.port().to_string());
27+
port_ = base_uri.port().to_string();
2828
}
2929

3030
if (base_uri.has_path()) {
31-
set_path(base_uri.path().to_string());
31+
path_ = base_uri.path().to_string();
3232
}
3333

3434
if (base_uri.has_query()) {
35-
append_query(base_uri.query().to_string());
35+
query_ = base_uri.query().to_string();
3636
}
3737

3838
if (base_uri.has_fragment()) {
39-
set_fragment(base_uri.fragment().to_string());
39+
fragment_ = base_uri.fragment().to_string();
4040
}
4141
}
4242

4343
uri_builder::~uri_builder() noexcept {}
4444

4545
network::uri uri_builder::uri() const { return network::uri(*this); }
4646

47-
void uri_builder::set_scheme(string_type scheme) {
47+
void uri_builder::set_scheme(string_type &&scheme) {
4848
// validate scheme is valid and normalize
4949
scheme_ = scheme;
5050
detail::transform(*scheme_, std::begin(*scheme_),
5151
[] (char ch) { return std::tolower(ch, std::locale()); });
5252
}
5353

54-
void uri_builder::set_user_info(string_type user_info) {
54+
void uri_builder::set_user_info(string_type &&user_info) {
5555
user_info_ = string_type();
5656
network::uri::encode_user_info(std::begin(user_info), std::end(user_info),
5757
std::back_inserter(*user_info_));
@@ -62,15 +62,15 @@ uri_builder &uri_builder::clear_user_info() {
6262
return *this;
6363
}
6464

65-
void uri_builder::set_host(string_type host) {
65+
void uri_builder::set_host(string_type &&host) {
6666
host_ = string_type();
6767
network::uri::encode_host(std::begin(host), std::end(host),
6868
std::back_inserter(*host_));
6969
detail::transform(*host_, std::begin(*host_),
7070
[](char ch) { return std::tolower(ch, std::locale()); });
7171
}
7272

73-
void uri_builder::set_port(string_type port) {
73+
void uri_builder::set_port(string_type &&port) {
7474
port_ = string_type();
7575
network::uri::encode_port(std::begin(port), std::end(port),
7676
std::back_inserter(*port_));
@@ -81,7 +81,7 @@ uri_builder &uri_builder::clear_port() {
8181
return *this;
8282
}
8383

84-
void uri_builder::set_authority(string_type authority) {
84+
void uri_builder::set_authority(string_type &&authority) {
8585
optional<detail::uri_part> user_info, host, port;
8686
uri::string_view view(authority);
8787
uri::const_iterator it = std::begin(view), last = std::end(view);
@@ -100,7 +100,7 @@ void uri_builder::set_authority(string_type authority) {
100100
}
101101
}
102102

103-
void uri_builder::set_path(string_type path) {
103+
void uri_builder::set_path(string_type &&path) {
104104
path_ = string_type();
105105
network::uri::encode_path(std::begin(path), std::end(path),
106106
std::back_inserter(*path_));
@@ -111,36 +111,35 @@ uri_builder &uri_builder::clear_path() {
111111
return *this;
112112
}
113113

114-
void uri_builder::append_query(string_type query) {
114+
void uri_builder::append_query_component(string_type &&name) {
115115
if (!query_) {
116116
query_ = string_type();
117117
}
118118
else {
119119
query_->append("&");
120120
}
121-
network::uri::encode_query(std::begin(query), std::end(query),
122-
std::back_inserter(*query_));
121+
network::uri::encode_query_component(
122+
std::begin(name), std::end(name), std::back_inserter(*query_));
123123
}
124124

125-
void uri_builder::append_query_key_value_pair(string_type key, string_type value) {
125+
void uri_builder::append_query_key_value_pair(string_type &&key, string_type &&value) {
126126
if (!query_) {
127127
query_ = string_type();
128128
} else {
129129
query_->push_back('&');
130130
}
131-
detail::encode_query_component(std::begin(key), std::end(key),
132-
std::back_inserter(*query_));
133-
query_->push_back('=');
134-
detail::encode_query_component(std::begin(value), std::end(value),
135-
std::back_inserter(*query_));
131+
network::uri::encode_query_key_value_pair(
132+
std::begin(key), std::end(key),
133+
std::begin(value), std::end(value),
134+
std::back_inserter(*query_));
136135
}
137136

138137
uri_builder &uri_builder::clear_query() {
139138
query_ = network::nullopt;
140139
return *this;
141140
}
142141

143-
void uri_builder::set_fragment(string_type fragment) {
142+
void uri_builder::set_fragment(string_type &&fragment) {
144143
fragment_ = string_type();
145144
network::uri::encode_fragment(std::begin(fragment), std::end(fragment),
146145
std::back_inserter(*fragment_));

0 commit comments

Comments
 (0)