From bff008fbc8fb940b2974e412554490ee4e2d2320 Mon Sep 17 00:00:00 2001 From: ZHANG Dapeng Date: Fri, 9 Nov 2018 13:39:01 -0800 Subject: [PATCH] core: Emit bin-headers with unpadded encoding Following the [grpc PROTOCOL-HTTP2 spec](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md) "Note that HTTP2 does not allow arbitrary octet sequences for header values so binary header values must be encoded using Base64 as per https://tools.ietf.org/html/rfc4648#section-4. Implementations MUST accept padded and un-padded values and should emit un-padded values. " --- core/src/main/java/io/grpc/InternalMetadata.java | 8 ++++++++ core/src/main/java/io/grpc/Metadata.java | 4 +++- .../main/java/io/grpc/internal/TransportFrameUtil.java | 3 ++- .../java/io/grpc/internal/TransportFrameUtilTest.java | 2 +- .../java/io/grpc/netty/GrpcHttp2InboundHeadersTest.java | 4 ++-- 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/io/grpc/InternalMetadata.java b/core/src/main/java/io/grpc/InternalMetadata.java index 3e19702a2c..cfd6fa5c0e 100644 --- a/core/src/main/java/io/grpc/InternalMetadata.java +++ b/core/src/main/java/io/grpc/InternalMetadata.java @@ -16,6 +16,7 @@ package io.grpc; +import com.google.common.io.BaseEncoding; import io.grpc.Metadata.AsciiMarshaller; import io.grpc.Metadata.Key; import java.nio.charset.Charset; @@ -43,6 +44,13 @@ public final class InternalMetadata { @Internal public static final Charset US_ASCII = Charset.forName("US-ASCII"); + /** + * An instance of base64 encoder that omits padding. + */ + @Internal + public static final BaseEncoding BASE64_ENCODING_OMIT_PADDING + = Metadata.BASE64_ENCODING_OMIT_PADDING; + @Internal public static Key keyOf(String name, TrustedAsciiMarshaller marshaller) { boolean isPseudo = name != null && !name.isEmpty() && name.charAt(0) == ':'; diff --git a/core/src/main/java/io/grpc/Metadata.java b/core/src/main/java/io/grpc/Metadata.java index bd9e62760e..89af041c77 100644 --- a/core/src/main/java/io/grpc/Metadata.java +++ b/core/src/main/java/io/grpc/Metadata.java @@ -104,6 +104,8 @@ public final class Metadata { } }; + static final BaseEncoding BASE64_ENCODING_OMIT_PADDING = BaseEncoding.base64().omitPadding(); + /** * Constructor called by the transport layer when it receives binary metadata. Metadata will * mutate the passed in array. @@ -466,7 +468,7 @@ public final class Metadata { String headerName = new String(name(i), US_ASCII); sb.append(headerName).append('='); if (headerName.endsWith(BINARY_HEADER_SUFFIX)) { - sb.append(BaseEncoding.base64().encode(value(i))); + sb.append(BASE64_ENCODING_OMIT_PADDING.encode(value(i))); } else { String headerValue = new String(value(i), US_ASCII); sb.append(headerValue); diff --git a/core/src/main/java/io/grpc/internal/TransportFrameUtil.java b/core/src/main/java/io/grpc/internal/TransportFrameUtil.java index 84780315fd..71175ae1ba 100644 --- a/core/src/main/java/io/grpc/internal/TransportFrameUtil.java +++ b/core/src/main/java/io/grpc/internal/TransportFrameUtil.java @@ -61,7 +61,8 @@ public final class TransportFrameUtil { if (endsWith(key, binaryHeaderSuffixBytes)) { // Binary header. serializedHeaders[k] = key; - serializedHeaders[k + 1] = BaseEncoding.base64().encode(value).getBytes(US_ASCII); + serializedHeaders[k + 1] + = InternalMetadata.BASE64_ENCODING_OMIT_PADDING.encode(value).getBytes(US_ASCII); k += 2; } else { // Non-binary header. diff --git a/core/src/test/java/io/grpc/internal/TransportFrameUtilTest.java b/core/src/test/java/io/grpc/internal/TransportFrameUtilTest.java index 4d0f6ed0b5..8d6bba0f74 100644 --- a/core/src/test/java/io/grpc/internal/TransportFrameUtilTest.java +++ b/core/src/test/java/io/grpc/internal/TransportFrameUtilTest.java @@ -140,7 +140,7 @@ public class TransportFrameUtilTest { } private static byte[] base64Encode(byte[] input) { - return BaseEncoding.base64().encode(input).getBytes(US_ASCII); + return InternalMetadata.BASE64_ENCODING_OMIT_PADDING.encode(input).getBytes(US_ASCII); } } diff --git a/netty/src/test/java/io/grpc/netty/GrpcHttp2InboundHeadersTest.java b/netty/src/test/java/io/grpc/netty/GrpcHttp2InboundHeadersTest.java index 25c275b679..62c2012895 100644 --- a/netty/src/test/java/io/grpc/netty/GrpcHttp2InboundHeadersTest.java +++ b/netty/src/test/java/io/grpc/netty/GrpcHttp2InboundHeadersTest.java @@ -16,12 +16,12 @@ package io.grpc.netty; +import static io.grpc.InternalMetadata.BASE64_ENCODING_OMIT_PADDING; import static io.netty.util.AsciiString.of; import static junit.framework.TestCase.assertNotSame; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; -import com.google.common.io.BaseEncoding; import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2InboundHeaders; import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2RequestHeaders; import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2ResponseHeaders; @@ -69,7 +69,7 @@ public class GrpcHttp2InboundHeadersTest { byte[] data = new byte[100]; new Random().nextBytes(data); - headers.add(of("foo-bin"), of(BaseEncoding.base64().encode(data))); + headers.add(of("foo-bin"), of(BASE64_ENCODING_OMIT_PADDING.encode(data))); assertEquals(1, headers.size());