Skip to content

Commit

Permalink
url encoded form data uses '+' for ' ' according to w3 (square#6518)
Browse files Browse the repository at this point in the history
* url encoded form data uses '+' for ' ' according to w3

* added comment when plusIsSpace = false (square#6518)

(cherry picked from commit b779d7d)
  • Loading branch information
emrecosar authored and yschimke committed Dec 2, 2023
1 parent cdf8a6e commit f610774
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 10 deletions.
4 changes: 2 additions & 2 deletions okhttp/src/main/kotlin/okhttp3/FormBody.kt
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ class FormBody internal constructor(
fun add(name: String, value: String) = apply {
names += name.canonicalize(
encodeSet = FORM_ENCODE_SET,
plusIsSpace = true,
plusIsSpace = false, // plus is encoded as `%25`, space is encoded as plus
charset = charset
)
values += value.canonicalize(
encodeSet = FORM_ENCODE_SET,
plusIsSpace = true,
plusIsSpace = false, // plus is encoded as `%25`, space is encoded as plus
charset = charset
)
}
Expand Down
6 changes: 5 additions & 1 deletion okhttp/src/main/kotlin/okhttp3/HttpUrl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1564,7 +1564,7 @@ class HttpUrl internal constructor(
internal const val QUERY_COMPONENT_REENCODE_SET = " \"'<>#&="
internal const val QUERY_COMPONENT_ENCODE_SET = " !\"#$&'(),/:;<=>?@[]\\^`{|}~"
internal const val QUERY_COMPONENT_ENCODE_SET_URI = "\\^`{|}"
internal const val FORM_ENCODE_SET = " \"':;<=>@[]^`{}|/\\?#&!$(),~"
internal const val FORM_ENCODE_SET = " !\"#$&'()+,/:;<=>?@[\\]^`{|}~"
internal const val FRAGMENT_ENCODE_SET = ""
internal const val FRAGMENT_ENCODE_SET_URI = " \"#<>\\^`{|}"

Expand Down Expand Up @@ -1831,6 +1831,10 @@ class HttpUrl internal constructor(
if (alreadyEncoded && (codePoint == '\t'.toInt() || codePoint == '\n'.toInt() ||
codePoint == '\u000c'.toInt() || codePoint == '\r'.toInt())) {
// Skip this character.
} else if (codePoint == ' '.toInt() && encodeSet == FORM_ENCODE_SET) {
// Encode ' ' as '+'
// @see -> https://www.w3.org/TR/2014/REC-html5-20141028/single-page.html#url-encoded-form-data
writeUtf8("+")
} else if (codePoint == '+'.toInt() && plusIsSpace) {
// Encode '+' as '%2B' since we permit ' ' to be encoded as either '+' or '%20'.
writeUtf8(if (alreadyEncoded) "+" else "%2B")
Expand Down
14 changes: 7 additions & 7 deletions okhttp/src/test/java/okhttp3/FormBodyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,16 @@ public final class FormBodyTest {

assertThat(body.size()).isEqualTo(3);

assertThat(body.encodedName(0)).isEqualTo("a%2B%3D%26%20b");
assertThat(body.encodedName(1)).isEqualTo("space%2C%20the");
assertThat(body.encodedName(0)).isEqualTo("a%2B%3D%26+b");
assertThat(body.encodedName(1)).isEqualTo("space%2C+the");
assertThat(body.encodedName(2)).isEqualTo("%2525");

assertThat(body.name(0)).isEqualTo("a+=& b");
assertThat(body.name(1)).isEqualTo("space, the");
assertThat(body.name(2)).isEqualTo("%25");

assertThat(body.encodedValue(0)).isEqualTo("c%2B%3D%26%20d");
assertThat(body.encodedValue(1)).isEqualTo("final%20frontier");
assertThat(body.encodedValue(0)).isEqualTo("c%2B%3D%26+d");
assertThat(body.encodedValue(1)).isEqualTo("final+frontier");
assertThat(body.encodedValue(2)).isEqualTo("%2525");

assertThat(body.value(0)).isEqualTo("c+=& d");
Expand All @@ -52,7 +52,7 @@ public final class FormBodyTest {
assertThat(body.contentType().toString()).isEqualTo(
"application/x-www-form-urlencoded");

String expected = "a%2B%3D%26%20b=c%2B%3D%26%20d&space%2C%20the=final%20frontier&%2525=%2525";
String expected = "a%2B%3D%26+b=c%2B%3D%26+d&space%2C+the=final+frontier&%2525=%2525";
assertThat(body.contentLength()).isEqualTo(expected.length());

Buffer out = new Buffer();
Expand All @@ -67,7 +67,7 @@ public final class FormBodyTest {
.addEncoded("%25", "%25")
.build();

String expected = "a+%3D%26%20b=c+%3D%26%20d&e+%3D%26%20f=g+%3D%26%20h&%25=%25";
String expected = "a+%3D%26+b=c+%3D%26+d&e+%3D%26+f=g+%3D%26+h&%25=%25";
Buffer out = new Buffer();
body.writeTo(out);
assertThat(out.readUtf8()).isEqualTo(expected);
Expand Down Expand Up @@ -149,7 +149,7 @@ public final class FormBodyTest {
assertThat(formEncode(30)).isEqualTo("%1E");
assertThat(formEncode(31)).isEqualTo("%1F");
// Browsers use '+' for space.
assertThat(formEncode(32)).isEqualTo("%20");
assertThat(formEncode(32)).isEqualTo("+");
assertThat(formEncode(33)).isEqualTo("%21");
assertThat(formEncode(34)).isEqualTo("%22");
assertThat(formEncode(35)).isEqualTo("%23");
Expand Down

0 comments on commit f610774

Please sign in to comment.