mirror of
https://github.com/square/okhttp.git
synced 2026-01-17 08:42:25 +03:00
New FormEncodingBuilder.addEncoded() API.
This is a behavior change: previously we'd encode '+' as plus and encode characters that don't need it, including ','. Now we use the same rules as HttpUrl.
This commit is contained in:
@@ -25,11 +25,12 @@ public final class FormEncodingBuilderTest {
|
||||
RequestBody formEncoding = new FormEncodingBuilder()
|
||||
.add("a&b", "c=d")
|
||||
.add("space, the", "final frontier")
|
||||
.add("%25", "%25")
|
||||
.build();
|
||||
|
||||
assertEquals("application/x-www-form-urlencoded", formEncoding.contentType().toString());
|
||||
|
||||
String expected = "a%26b=c%3Dd&space%2C+the=final+frontier";
|
||||
String expected = "a%26b=c%3Dd&space,%20the=final%20frontier&%2525=%2525";
|
||||
assertEquals(expected.length(), formEncoding.contentLength());
|
||||
|
||||
Buffer out = new Buffer();
|
||||
@@ -37,6 +38,19 @@ public final class FormEncodingBuilderTest {
|
||||
assertEquals(expected, out.readUtf8());
|
||||
}
|
||||
|
||||
@Test public void addEncoded() throws Exception {
|
||||
RequestBody formEncoding = new FormEncodingBuilder()
|
||||
.addEncoded("a+=& b", "c+=& d")
|
||||
.addEncoded("e+=& f", "g+=& h")
|
||||
.addEncoded("%25", "%25")
|
||||
.build();
|
||||
|
||||
String expected = "a%20%3D%26%20b=c%20%3D%26%20d&e%20%3D%26%20f=g%20%3D%26%20h&%25=%25";
|
||||
Buffer out = new Buffer();
|
||||
formEncoding.writeTo(out);
|
||||
assertEquals(expected, out.readUtf8());
|
||||
}
|
||||
|
||||
@Test public void encodedPair() throws Exception {
|
||||
RequestBody formEncoding = new FormEncodingBuilder()
|
||||
.add("sim", "ple")
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.squareup.okhttp;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import okio.Buffer;
|
||||
|
||||
/**
|
||||
@@ -34,13 +32,24 @@ public final class FormEncodingBuilder {
|
||||
if (content.size() > 0) {
|
||||
content.writeByte('&');
|
||||
}
|
||||
try {
|
||||
content.writeUtf8(URLEncoder.encode(name, "UTF-8"));
|
||||
content.writeByte('=');
|
||||
content.writeUtf8(URLEncoder.encode(value, "UTF-8"));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError(e);
|
||||
HttpUrl.canonicalize(content, name, 0, name.length(),
|
||||
HttpUrl.QUERY_COMPONENT_ENCODE_SET, false, true);
|
||||
content.writeByte('=');
|
||||
HttpUrl.canonicalize(content, value, 0, value.length(),
|
||||
HttpUrl.QUERY_COMPONENT_ENCODE_SET, false, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Add new key-value pair. */
|
||||
public FormEncodingBuilder addEncoded(String name, String value) {
|
||||
if (content.size() > 0) {
|
||||
content.writeByte('&');
|
||||
}
|
||||
HttpUrl.canonicalize(content, name, 0, name.length(),
|
||||
HttpUrl.QUERY_COMPONENT_ENCODE_SET, true, true);
|
||||
content.writeByte('=');
|
||||
HttpUrl.canonicalize(content, value, 0, value.length(),
|
||||
HttpUrl.QUERY_COMPONENT_ENCODE_SET, true, true);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -255,12 +255,12 @@ import okio.Buffer;
|
||||
public final class HttpUrl {
|
||||
private static final char[] HEX_DIGITS =
|
||||
{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
|
||||
private static final String USERNAME_ENCODE_SET = " \"':;<=>@[]^`{}|/\\?#";
|
||||
private static final String PASSWORD_ENCODE_SET = " \"':;<=>@[]\\^`{}|/\\?#";
|
||||
private static final String PATH_SEGMENT_ENCODE_SET = " \"<>^`{}|/\\?#";
|
||||
private static final String QUERY_ENCODE_SET = " \"'<>#";
|
||||
private static final String QUERY_COMPONENT_ENCODE_SET = " \"'<>#&=";
|
||||
private static final String FRAGMENT_ENCODE_SET = "";
|
||||
static final String USERNAME_ENCODE_SET = " \"':;<=>@[]^`{}|/\\?#";
|
||||
static final String PASSWORD_ENCODE_SET = " \"':;<=>@[]\\^`{}|/\\?#";
|
||||
static final String PATH_SEGMENT_ENCODE_SET = " \"<>^`{}|/\\?#";
|
||||
static final String QUERY_ENCODE_SET = " \"'<>#";
|
||||
static final String QUERY_COMPONENT_ENCODE_SET = " \"'<>#&=";
|
||||
static final String FRAGMENT_ENCODE_SET = "";
|
||||
|
||||
/** Either "http" or "https". */
|
||||
private final String scheme;
|
||||
@@ -1422,10 +1422,10 @@ public final class HttpUrl {
|
||||
|| (codePoint == '%' && !alreadyEncoded)
|
||||
|| (query && codePoint == '+')) {
|
||||
// Slow path: the character at i requires encoding!
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append(input, pos, i);
|
||||
Buffer out = new Buffer();
|
||||
out.writeUtf8(input, pos, i);
|
||||
canonicalize(out, input, i, limit, encodeSet, alreadyEncoded, query);
|
||||
return out.toString();
|
||||
return out.readUtf8();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1433,7 +1433,7 @@ public final class HttpUrl {
|
||||
return input.substring(pos, limit);
|
||||
}
|
||||
|
||||
static void canonicalize(StringBuilder out, String input, int pos, int limit,
|
||||
static void canonicalize(Buffer out, String input, int pos, int limit,
|
||||
String encodeSet, boolean alreadyEncoded, boolean query) {
|
||||
Buffer utf8Buffer = null; // Lazily allocated.
|
||||
int codePoint;
|
||||
@@ -1444,7 +1444,7 @@ public final class HttpUrl {
|
||||
// Skip this character.
|
||||
} else if (query && codePoint == '+') {
|
||||
// HTML permits space to be encoded as '+'. We use '%20' to avoid special cases.
|
||||
out.append(alreadyEncoded ? "%20" : "%2B");
|
||||
out.writeUtf8(alreadyEncoded ? "%20" : "%2B");
|
||||
} else if (codePoint < 0x20
|
||||
|| codePoint >= 0x7f
|
||||
|| encodeSet.indexOf(codePoint) != -1
|
||||
@@ -1456,13 +1456,13 @@ public final class HttpUrl {
|
||||
utf8Buffer.writeUtf8CodePoint(codePoint);
|
||||
while (!utf8Buffer.exhausted()) {
|
||||
int b = utf8Buffer.readByte() & 0xff;
|
||||
out.append('%');
|
||||
out.append(HEX_DIGITS[(b >> 4) & 0xf]);
|
||||
out.append(HEX_DIGITS[b & 0xf]);
|
||||
out.writeByte('%');
|
||||
out.writeByte(HEX_DIGITS[(b >> 4) & 0xf]);
|
||||
out.writeByte(HEX_DIGITS[b & 0xf]);
|
||||
}
|
||||
} else {
|
||||
// This character doesn't need encoding. Just copy it over.
|
||||
out.append((char) codePoint);
|
||||
out.writeUtf8CodePoint(codePoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user