netty: Add toString() to GrpcHttp2InboundHeaders. Fixes #2341. (#2342)

Binary header values are printed in their base64 encoded form.

The GrpcHttpOutboundHeaders, as mentioned in the issue, don't seem to be affected by this regression. The toString() method seems fine.
This commit is contained in:
Jakob Buchgraber 2016-10-14 18:57:08 +02:00 committed by GitHub
parent abb4a2a393
commit 1e1c71d74c
2 changed files with 97 additions and 1 deletions

View File

@ -349,6 +349,27 @@ abstract class GrpcHttp2HeadersDecoder implements Http2HeadersDecoder,
public int size() {
return numHeaders();
}
protected static void appendNameAndValue(StringBuilder builder, CharSequence name,
CharSequence value, boolean prependSeparator) {
if (prependSeparator) {
builder.append(", ");
}
builder.append(name).append(": ").append(value);
}
protected final String namesAndValuesToString() {
StringBuilder builder = new StringBuilder();
boolean prependSeparator = false;
for (int i = 0; i < namesAndValuesIdx; i += 2) {
String name = new String(namesAndValues[i], US_ASCII);
// If binary headers, the value is base64 encoded.
AsciiString value = values[i / 2];
appendNameAndValue(builder, name, value, prependSeparator);
prependSeparator = true;
}
return builder.toString();
}
}
/**
@ -439,7 +460,6 @@ abstract class GrpcHttp2HeadersDecoder implements Http2HeadersDecoder,
return scheme;
}
/**
* This method is called in tests only.
*/
@ -480,6 +500,43 @@ abstract class GrpcHttp2HeadersDecoder implements Http2HeadersDecoder,
size += super.size();
return size;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()).append('[');
boolean prependSeparator = false;
if (path != null) {
appendNameAndValue(builder, PATH_HEADER, path, prependSeparator);
prependSeparator = true;
}
if (authority != null) {
appendNameAndValue(builder, AUTHORITY_HEADER, authority, prependSeparator);
prependSeparator = true;
}
if (method != null) {
appendNameAndValue(builder, METHOD_HEADER, method, prependSeparator);
prependSeparator = true;
}
if (scheme != null) {
appendNameAndValue(builder, SCHEME_HEADER, scheme, prependSeparator);
prependSeparator = true;
}
if (te != null) {
appendNameAndValue(builder, TE_HEADER, te, prependSeparator);
}
String namesAndValues = namesAndValuesToString();
if (builder.length() > 0 && namesAndValues.length() > 0) {
builder.append(", ");
}
builder.append(namesAndValues);
builder.append(']');
return builder.toString();
}
}
/**
@ -507,5 +564,12 @@ abstract class GrpcHttp2HeadersDecoder implements Http2HeadersDecoder,
AsciiString name = requireAsciiString(csName);
return get(name);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()).append('[');
builder.append(namesAndValuesToString()).append(']');
return builder.toString();
}
}
}

View File

@ -33,7 +33,9 @@ package io.grpc.netty;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_TABLE_SIZE;
import static io.netty.util.AsciiString.of;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import io.grpc.netty.GrpcHttp2HeadersDecoder.GrpcHttp2ClientHeadersDecoder;
import io.grpc.netty.GrpcHttp2HeadersDecoder.GrpcHttp2ServerHeadersDecoder;
@ -86,6 +88,13 @@ public class GrpcHttp2HeadersDecoderTest {
assertEquals(headers.get(of(":authority")), decodedHeaders.authority());
assertEquals(headers.get(of("custom")), decodedHeaders.get(of("custom")));
assertEquals(headers.size(), decodedHeaders.size());
String toString = decodedHeaders.toString();
assertContainsKeyAndValue(toString, ":scheme", decodedHeaders.scheme());
assertContainsKeyAndValue(toString, ":method", decodedHeaders.method());
assertContainsKeyAndValue(toString, ":path", decodedHeaders.path());
assertContainsKeyAndValue(toString, ":authority", decodedHeaders.authority());
assertContainsKeyAndValue(toString, "custom", decodedHeaders.get(of("custom")));
}
@Test
@ -103,5 +112,28 @@ public class GrpcHttp2HeadersDecoderTest {
assertEquals(headers.get(of(":status")), decodedHeaders.get(of(":status")));
assertEquals(headers.get(of("custom")), decodedHeaders.get(of("custom")));
assertEquals(headers.size(), decodedHeaders.size());
String toString = decodedHeaders.toString();
assertContainsKeyAndValue(toString, ":status", decodedHeaders.get(of(":status")));
assertContainsKeyAndValue(toString, "custom", decodedHeaders.get(of("custom")));
}
@Test
public void decode_emptyHeaders() throws Http2Exception {
Http2HeadersDecoder decoder = new GrpcHttp2ClientHeadersDecoder(8192);
Http2HeadersEncoder encoder =
new DefaultHttp2HeadersEncoder(DEFAULT_HEADER_TABLE_SIZE, NEVER_SENSITIVE);
ByteBuf encodedHeaders = ReferenceCountUtil.releaseLater(Unpooled.buffer());
encoder.encodeHeaders(new DefaultHttp2Headers(false), encodedHeaders);
Http2Headers decodedHeaders = decoder.decodeHeaders(encodedHeaders);
assertEquals(0, decodedHeaders.size());
assertThat(decodedHeaders.toString(), containsString("[]"));
}
private static void assertContainsKeyAndValue(String str, CharSequence key, CharSequence value) {
assertThat(str, containsString(key.toString()));
assertThat(str, containsString(value.toString()));
}
}