mirror of https://github.com/grpc/grpc-java.git
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:
parent
cab5966415
commit
bff008fbc8
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package io.grpc;
|
package io.grpc;
|
||||||
|
|
||||||
|
import com.google.common.io.BaseEncoding;
|
||||||
import io.grpc.Metadata.AsciiMarshaller;
|
import io.grpc.Metadata.AsciiMarshaller;
|
||||||
import io.grpc.Metadata.Key;
|
import io.grpc.Metadata.Key;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
@ -43,6 +44,13 @@ public final class InternalMetadata {
|
||||||
@Internal
|
@Internal
|
||||||
public static final Charset US_ASCII = Charset.forName("US-ASCII");
|
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
|
@Internal
|
||||||
public static <T> Key<T> keyOf(String name, TrustedAsciiMarshaller<T> marshaller) {
|
public static <T> Key<T> keyOf(String name, TrustedAsciiMarshaller<T> marshaller) {
|
||||||
boolean isPseudo = name != null && !name.isEmpty() && name.charAt(0) == ':';
|
boolean isPseudo = name != null && !name.isEmpty() && name.charAt(0) == ':';
|
||||||
|
|
|
||||||
|
|
@ -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
|
* Constructor called by the transport layer when it receives binary metadata. Metadata will
|
||||||
* mutate the passed in array.
|
* mutate the passed in array.
|
||||||
|
|
@ -466,7 +468,7 @@ public final class Metadata {
|
||||||
String headerName = new String(name(i), US_ASCII);
|
String headerName = new String(name(i), US_ASCII);
|
||||||
sb.append(headerName).append('=');
|
sb.append(headerName).append('=');
|
||||||
if (headerName.endsWith(BINARY_HEADER_SUFFIX)) {
|
if (headerName.endsWith(BINARY_HEADER_SUFFIX)) {
|
||||||
sb.append(BaseEncoding.base64().encode(value(i)));
|
sb.append(BASE64_ENCODING_OMIT_PADDING.encode(value(i)));
|
||||||
} else {
|
} else {
|
||||||
String headerValue = new String(value(i), US_ASCII);
|
String headerValue = new String(value(i), US_ASCII);
|
||||||
sb.append(headerValue);
|
sb.append(headerValue);
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,8 @@ public final class TransportFrameUtil {
|
||||||
if (endsWith(key, binaryHeaderSuffixBytes)) {
|
if (endsWith(key, binaryHeaderSuffixBytes)) {
|
||||||
// Binary header.
|
// Binary header.
|
||||||
serializedHeaders[k] = key;
|
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;
|
k += 2;
|
||||||
} else {
|
} else {
|
||||||
// Non-binary header.
|
// Non-binary header.
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ public class TransportFrameUtilTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] base64Encode(byte[] input) {
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,12 +16,12 @@
|
||||||
|
|
||||||
package io.grpc.netty;
|
package io.grpc.netty;
|
||||||
|
|
||||||
|
import static io.grpc.InternalMetadata.BASE64_ENCODING_OMIT_PADDING;
|
||||||
import static io.netty.util.AsciiString.of;
|
import static io.netty.util.AsciiString.of;
|
||||||
import static junit.framework.TestCase.assertNotSame;
|
import static junit.framework.TestCase.assertNotSame;
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
import com.google.common.io.BaseEncoding;
|
|
||||||
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2InboundHeaders;
|
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2InboundHeaders;
|
||||||
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2RequestHeaders;
|
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2RequestHeaders;
|
||||||
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2ResponseHeaders;
|
import io.grpc.netty.GrpcHttp2HeadersUtils.GrpcHttp2ResponseHeaders;
|
||||||
|
|
@ -69,7 +69,7 @@ public class GrpcHttp2InboundHeadersTest {
|
||||||
|
|
||||||
byte[] data = new byte[100];
|
byte[] data = new byte[100];
|
||||||
new Random().nextBytes(data);
|
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());
|
assertEquals(1, headers.size());
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue