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. "
This commit is contained in:
ZHANG Dapeng 2018-11-09 13:39:01 -08:00 committed by GitHub
parent cab5966415
commit bff008fbc8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 16 additions and 5 deletions

View File

@ -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 <T> Key<T> keyOf(String name, TrustedAsciiMarshaller<T> marshaller) {
boolean isPseudo = name != null && !name.isEmpty() && name.charAt(0) == ':';

View File

@ -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);

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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());