Optimize DefaultHeaders#toString and implement HttpHeaders#toString

Motivation:

For debugging/logging purpose, it would be convenient to have
HttpHeaders#toString implemented.

DefaultHeaders does implement toString be the implementation is suboptimal and allocates a Set for the names and Lists for values.

Modification:

* Introduce HeadersUtil#toString that provides a convenient optimized helper to implement toString for various headers implementations
* Have DefaultHeaders#toString and HttpHeaders#toString delegate their toString implementation to HeadersUtil

Result:

Convenient HttpHeaders#toString. Optimized DefaultHeaders#toString.
This commit is contained in:
Stephane Landelle 2017-11-21 11:31:07 +01:00 committed by Norman Maurer
parent b1cc5835ac
commit e420f857fa
4 changed files with 52 additions and 11 deletions

View File

@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.handler.codec.DateFormatter;
import io.netty.handler.codec.Headers;
import io.netty.handler.codec.HeadersUtils;
import io.netty.util.AsciiString;
import io.netty.util.CharsetUtil;
@ -1687,4 +1688,9 @@ public abstract class HttpHeaders implements Iterable<Map.Entry<String, String>>
public boolean contains(CharSequence name, CharSequence value, boolean ignoreCase) {
return contains(name.toString(), value.toString(), ignoreCase);
}
@Override
public String toString() {
return HeadersUtils.toString(getClass(), iteratorCharSequence(), size());
}
}

View File

@ -209,6 +209,26 @@ public class DefaultHttpHeadersTest {
assertDefaultValues(headers, HeaderValue.THREE);
}
@Test
public void toStringOnEmptyHeaders() {
assertEquals("DefaultHttpHeaders[]", newDefaultDefaultHttpHeaders().toString());
}
@Test
public void toStringOnSingleHeader() {
assertEquals("DefaultHttpHeaders[foo: bar]", newDefaultDefaultHttpHeaders()
.add("foo", "bar")
.toString());
}
@Test
public void toStringOnMultipleHeaders() {
assertEquals("DefaultHttpHeaders[foo: bar, baz: qix]", newDefaultDefaultHttpHeaders()
.add("foo", "bar")
.add("baz", "qix")
.toString());
}
private static void assertDefaultValues(final DefaultHttpHeaders headers, final HeaderValue headerValue) {
assertTrue(contentEquals(headerValue.asList().get(0), headers.get(HEADER_NAME)));
List<CharSequence> expected = headerValue.asList();

View File

@ -889,17 +889,7 @@ public class DefaultHeaders<K, V, T extends Headers<K, V, T>> implements Headers
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getSimpleName()).append('[');
String separator = "";
for (K name : names()) {
List<V> values = getAll(name);
for (int i = 0; i < values.size(); ++i) {
builder.append(separator);
builder.append(name).append(": ").append(values.get(i));
separator = ", ";
}
}
return builder.append(']').toString();
return HeadersUtils.toString(getClass(), iterator(), size());
}
protected HeaderEntry<K, V> newHeaderEntry(int h, K name, V value, HeaderEntry<K, V> next) {

View File

@ -72,6 +72,31 @@ public final class HeadersUtils {
return new StringEntryIterator(headers.iterator());
}
/**
* Helper for implementing toString for {@link DefaultHeaders} and wrappers such as DefaultHttpHeaders.
* @param headersClass the class of headers
* @param headersIt the iterator on the actual headers
* @param size the size of the iterator
* @return a String representation of the headers
*/
public static <K, V> String toString(Class<?> headersClass, Iterator<Entry<K, V>> headersIt, int size) {
String simpleName = headersClass.getSimpleName();
if (size == 0) {
return simpleName + "[]";
} else {
// original capacity assumes 20 chars per headers
StringBuilder sb = new StringBuilder(simpleName.length() + 2 + size * 20)
.append(simpleName)
.append('[');
while (headersIt.hasNext()) {
Entry<?, ?> header = headersIt.next();
sb.append(header.getKey()).append(": ").append(header.getValue()).append(", ");
}
sb.setLength(sb.length() - 2);
return sb.append(']').toString();
}
}
/**
* {@link Headers#names()} and convert each element of {@link Set} to a {@link String}.
* @param headers the headers to get the names from