diff --git a/api/src/main/java/io/grpc/Metadata.java b/api/src/main/java/io/grpc/Metadata.java
index fba2659776b..f277b9cd12a 100644
--- a/api/src/main/java/io/grpc/Metadata.java
+++ b/api/src/main/java/io/grpc/Metadata.java
@@ -94,15 +94,19 @@ public byte[] parseBytes(byte[] serialized) {
* Simple metadata marshaller that encodes strings as is.
*
*
This should be used with ASCII strings that only contain the characters listed in the class
- * comment of {@link AsciiMarshaller}. Otherwise the output may be considered invalid and
- * discarded by the transport, or the call may fail.
+ * comment of {@link AsciiMarshaller}. Otherwise an {@link IllegalArgumentException} will be
+ * thrown.
*/
public static final AsciiMarshaller ASCII_STRING_MARSHALLER =
new AsciiMarshaller() {
@Override
public String toAsciiString(String value) {
- return value;
+ checkArgument(
+ value.chars().allMatch(c -> c >= 0x20 && c <= 0x7E),
+ "String \"%s\" contains non-printable ASCII characters",
+ value);
+ return value.trim();
}
@Override
diff --git a/api/src/test/java/io/grpc/MetadataTest.java b/api/src/test/java/io/grpc/MetadataTest.java
index 14ba8ca9b23..ed139256c86 100644
--- a/api/src/test/java/io/grpc/MetadataTest.java
+++ b/api/src/test/java/io/grpc/MetadataTest.java
@@ -478,6 +478,17 @@ public void createFromPartial() {
assertSame(anotherSalmon, h2.get(KEY_IMMUTABLE));
}
+ @Test
+ public void failNonPrintableAsciiCharacters() {
+ String value = "José";
+
+ thrown.expect(IllegalArgumentException.class);
+ thrown.expectMessage("String \"" + value + "\" contains non-printable ASCII characters");
+
+ Metadata metadata = new Metadata();
+ metadata.put(Metadata.Key.of("test-non-printable", Metadata.ASCII_STRING_MARSHALLER), value);
+ }
+
private static final class Fish {
private String name;