diff --git a/okhttp-tests/src/test/java/okhttp3/HeadersTest.java b/okhttp-tests/src/test/java/okhttp3/HeadersTest.java index e5dfaa3ca5a1..a431dbe124f5 100644 --- a/okhttp-tests/src/test/java/okhttp3/HeadersTest.java +++ b/okhttp-tests/src/test/java/okhttp3/HeadersTest.java @@ -121,6 +121,25 @@ public final class HeadersTest { } } + @Test public void addUnsafeNonAsciiRejectsUnicodeName() { + try { + Headers headers = new Headers.Builder() + .addUnsafeNonAscii("héader1", "value1") + .build(); + fail("Should have complained about invalid value"); + } catch (IllegalArgumentException expected) { + assertEquals("Unexpected char 0xe9 at 1 in header name: héader1", + expected.getMessage()); + } + } + + @Test public void addUnsafeNonAsciiAcceptsUnicodeValue() { + Headers headers = new Headers.Builder() + .addUnsafeNonAscii("header1", "valué1") + .build(); + assertEquals("header1: valué1\n", headers.toString()); + } + @Test public void ofThrowsOddNumberOfHeaders() { try { Headers.of("User-Agent", "OkHttp", "Content-Length"); diff --git a/okhttp/src/main/java/okhttp3/Headers.java b/okhttp/src/main/java/okhttp3/Headers.java index f55b2979d2f0..73552fbee041 100644 --- a/okhttp/src/main/java/okhttp3/Headers.java +++ b/okhttp/src/main/java/okhttp3/Headers.java @@ -220,7 +220,8 @@ public static Headers of(String... namesAndValues) { for (int i = 0; i < namesAndValues.length; i += 2) { String name = namesAndValues[i]; String value = namesAndValues[i + 1]; - checkNameAndValue(name, value); + checkName(name); + checkValue(value, name); } return new Headers(namesAndValues); @@ -241,7 +242,8 @@ public static Headers of(Map headers) { } String name = header.getKey().trim(); String value = header.getValue().trim(); - checkNameAndValue(name, value); + checkName(name); + checkValue(value, name); namesAndValues[i] = name; namesAndValues[i + 1] = value; i += 2; @@ -250,7 +252,7 @@ public static Headers of(Map headers) { return new Headers(namesAndValues); } - static void checkNameAndValue(String name, String value) { + static void checkName(String name) { if (name == null) throw new NullPointerException("name == null"); if (name.isEmpty()) throw new IllegalArgumentException("name is empty"); for (int i = 0, length = name.length(); i < length; i++) { @@ -260,6 +262,9 @@ static void checkNameAndValue(String name, String value) { "Unexpected char %#04x at %d in header name: %s", (int) c, i, name)); } } + } + + static void checkValue(String value, String name) { if (value == null) throw new NullPointerException("value for name " + name + " == null"); for (int i = 0, length = value.length(); i < length; i++) { char c = value.charAt(i); @@ -303,7 +308,17 @@ public Builder add(String line) { * Add a header with the specified name and value. Does validation of header names and values. */ public Builder add(String name, String value) { - checkNameAndValue(name, value); + checkName(name); + checkValue(value, name); + return addLenient(name, value); + } + + /** + * Add a header with the specified name and value. Does validation of header names, allowing + * non-ASCII values. + */ + public Builder addUnsafeNonAscii(String name, String value) { + checkName(name); return addLenient(name, value); } @@ -345,7 +360,8 @@ public Builder removeAll(String name) { * found, the existing values are replaced. */ public Builder set(String name, String value) { - checkNameAndValue(name, value); + checkName(name); + checkValue(value, name); removeAll(name); addLenient(name, value); return this;