aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Walters <rwalters@digitalstirling.com>2019-03-28 00:00:15 -0700
committerRichard Walters <rwalters@digitalstirling.com>2019-03-28 00:00:15 -0700
commit7cc97d98213436350624bcf5c38203b3116ca651 (patch)
tree44b8b13d35e5ac712041c3952c1fb938925bbce3
parent79d2e347dc32c4f491c4cd3476b4ffa1db3e4003 (diff)
Percent-encode '+' in the query portion
-rw-r--r--src/Uri.cpp17
-rw-r--r--test/src/UriTests.cpp13
2 files changed, 29 insertions, 1 deletions
diff --git a/src/Uri.cpp b/src/Uri.cpp
index b6b82e1..fef7fb6 100644
--- a/src/Uri.cpp
+++ b/src/Uri.cpp
@@ -99,6 +99,21 @@ namespace {
};
/**
+ * This is the character set almost corresponds to the "query" syntax
+ * specified in RFC 3986 (https://tools.ietf.org/html/rfc3986),
+ * leaving out "pct-encoded", except that '+' is also excluded, because
+ * for some web services (e.g. AWS S3) a '+' is treated as
+ * synonymous with a space (' ') and thus gets misinterpreted.
+ */
+ const Uri::CharacterSet QUERY_NOT_PCT_ENCODED_WITHOUT_PLUS{
+ UNRESERVED,
+ '!', '$', '&', '\'', '(', ')',
+ '*', ',', ';', '=',
+ ':', '@',
+ '/', '?'
+ };
+
+ /**
* This is the character set corresponds to the "userinfo" syntax
* specified in RFC 3986 (https://tools.ietf.org/html/rfc3986),
* leaving out "pct-encoded".
@@ -1450,7 +1465,7 @@ namespace Uri {
++i;
}
if (impl_->hasQuery) {
- buffer << '?' << EncodeElement(impl_->query, QUERY_OR_FRAGMENT_NOT_PCT_ENCODED);
+ buffer << '?' << EncodeElement(impl_->query, QUERY_NOT_PCT_ENCODED_WITHOUT_PLUS);
}
if (impl_->hasFragment) {
buffer << '#' << EncodeElement(impl_->fragment, QUERY_OR_FRAGMENT_NOT_PCT_ENCODED);
diff --git a/test/src/UriTests.cpp b/test/src/UriTests.cpp
index 637bfb7..e3737c2 100644
--- a/test/src/UriTests.cpp
+++ b/test/src/UriTests.cpp
@@ -906,3 +906,16 @@ TEST(UriTests, ClearQuery) {
EXPECT_EQ("http://www.example.com/", uri.GenerateString());
EXPECT_FALSE(uri.HasQuery());
}
+
+TEST(UriTests, PercentEncodePlusInQueries) {
+ // Although RFC 3986 doesn't say anything about '+', some web services
+ // treat it the same as ' ' due to how HTML originally defined how
+ // to encode the query portion of a URL
+ // (see https://stackoverflow.com/questions/2678551/when-to-encode-space-to-plus-or-20).
+ //
+ // To avoid issues with these web services, make sure '+' is
+ // percent-encoded in a URI when the URI is encoded.
+ Uri::Uri uri;
+ uri.SetQuery("foo+bar");
+ EXPECT_EQ("?foo%2Bbar", uri.GenerateString());
+}