Commit 7a28452e authored by Harris Hancock's avatar Harris Hancock

Use application/x-www-form-urlencoded format for URL query strings

The main motivation here is to make sure we don't %-escape incoming pluses, but rather interpret them as spaces.
parent 4982c9e8
...@@ -132,6 +132,14 @@ KJ_TEST("parse / stringify URL") { ...@@ -132,6 +132,14 @@ KJ_TEST("parse / stringify URL") {
KJ_EXPECT(KJ_ASSERT_NONNULL(url.fragment) == "garply"); KJ_EXPECT(KJ_ASSERT_NONNULL(url.fragment) == "garply");
} }
{
auto url = parseAndCheck("https://capnproto.org/foo?bar%20baz=qux+quux",
"https://capnproto.org/foo?bar+baz=qux+quux");
KJ_ASSERT(url.query.size() == 1);
KJ_EXPECT(url.query[0].name == "bar baz");
KJ_EXPECT(url.query[0].value == "qux quux");
}
{ {
auto url = parseAndCheck("https://capnproto.org/foo/bar#garply"); auto url = parseAndCheck("https://capnproto.org/foo/bar#garply");
KJ_EXPECT(url.scheme == "https"); KJ_EXPECT(url.scheme == "https");
...@@ -232,7 +240,7 @@ KJ_TEST("URL percent encoding") { ...@@ -232,7 +240,7 @@ KJ_TEST("URL percent encoding") {
parseAndCheck( parseAndCheck(
"https://b b: bcd@capnproto.org/f o?b r=b z#q x", "https://b b: bcd@capnproto.org/f o?b r=b z#q x",
"https://b%20b:%20bcd@capnproto.org/f%20o?b%20r=b%20z#q%20x"); "https://b%20b:%20bcd@capnproto.org/f%20o?b+r=b+z#q%20x");
} }
KJ_TEST("URL relative paths") { KJ_TEST("URL relative paths") {
...@@ -340,6 +348,9 @@ KJ_TEST("parse relative URL") { ...@@ -340,6 +348,9 @@ KJ_TEST("parse relative URL") {
parseAndCheckRelative("https://capnproto.org/foo/bar?baz=qux#corge", parseAndCheckRelative("https://capnproto.org/foo/bar?baz=qux#corge",
"?grault", "?grault",
"https://capnproto.org/foo/bar?grault"); "https://capnproto.org/foo/bar?grault");
parseAndCheckRelative("https://capnproto.org/foo/bar?baz=qux#corge",
"?grault+garply=waldo",
"https://capnproto.org/foo/bar?grault+garply=waldo");
parseAndCheckRelative("https://capnproto.org/foo/bar?baz=qux#corge", parseAndCheckRelative("https://capnproto.org/foo/bar?baz=qux#corge",
"grault", "grault",
"https://capnproto.org/foo/grault"); "https://capnproto.org/foo/grault");
......
...@@ -88,6 +88,12 @@ String percentDecode(ArrayPtr<const char> text, bool& hadErrors) { ...@@ -88,6 +88,12 @@ String percentDecode(ArrayPtr<const char> text, bool& hadErrors) {
return kj::mv(result); return kj::mv(result);
} }
String percentDecodeQuery(ArrayPtr<const char> text, bool& hadErrors) {
auto result = decodeWwwForm(text);
if (result.hadErrors) hadErrors = true;
return kj::mv(result);
}
} // namespace } // namespace
Url::~Url() noexcept(false) {} Url::~Url() noexcept(false) {}
...@@ -195,9 +201,10 @@ Maybe<Url> Url::tryParse(StringPtr text, Context context) { ...@@ -195,9 +201,10 @@ Maybe<Url> Url::tryParse(StringPtr text, Context context) {
if (part.size() > 0) { if (part.size() > 0) {
KJ_IF_MAYBE(key, trySplit(part, '=')) { KJ_IF_MAYBE(key, trySplit(part, '=')) {
result.query.add(QueryParam { percentDecode(*key, err), percentDecode(part, err) }); result.query.add(QueryParam { percentDecodeQuery(*key, err),
percentDecodeQuery(part, err) });
} else { } else {
result.query.add(QueryParam { percentDecode(part, err), nullptr }); result.query.add(QueryParam { percentDecodeQuery(part, err), nullptr });
} }
} }
} while (text.startsWith("&")); } while (text.startsWith("&"));
...@@ -331,9 +338,10 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const { ...@@ -331,9 +338,10 @@ Maybe<Url> Url::tryParseRelative(StringPtr text) const {
if (part.size() > 0) { if (part.size() > 0) {
KJ_IF_MAYBE(key, trySplit(part, '=')) { KJ_IF_MAYBE(key, trySplit(part, '=')) {
result.query.add(QueryParam { percentDecode(*key, err), percentDecode(part, err) }); result.query.add(QueryParam { percentDecodeQuery(*key, err),
percentDecodeQuery(part, err) });
} else { } else {
result.query.add(QueryParam { percentDecode(part, err), nullptr }); result.query.add(QueryParam { percentDecodeQuery(part, err), nullptr });
} }
} }
} while (text.startsWith("&")); } while (text.startsWith("&"));
...@@ -407,10 +415,10 @@ String Url::toString(Context context) const { ...@@ -407,10 +415,10 @@ String Url::toString(Context context) const {
for (auto& param: query) { for (auto& param: query) {
chars.add(first ? '?' : '&'); chars.add(first ? '?' : '&');
first = false; first = false;
chars.addAll(encodeUriComponent(param.name)); chars.addAll(encodeWwwForm(param.name));
if (param.value.size() > 0) { if (param.value.size() > 0) {
chars.add('='); chars.add('=');
chars.addAll(encodeUriComponent(param.value)); chars.addAll(encodeWwwForm(param.value));
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment