From 81f9434ec70136ac2c7277937c3c837cbd7c80d2 Mon Sep 17 00:00:00 2001 From: Dmitriy Dumanskiy Date: Wed, 14 Jun 2017 21:15:58 +0300 Subject: [PATCH] Added test for multi header, HttpObjectDecoder performance improvement for multi header, removed empty else block. Motivation: For multi-line headers HttpObjectDecoder uses StringBuilder.append(a).append(b) pattern that could be easily replaced with regular a + b. Also oparations with a and b moved out from concat operation to make it friendly for StringOptimizeConcat optimization and thus - faster. Modification: StringBuilder.append(a).append(b) reaplced with a + b. Operations with a and b moved out from concat oparation. Result: Code simpler to read and faster. --- .../handler/codec/http/HttpObjectDecoder.java | 20 ++++++--------- .../codec/http/HttpRequestDecoderTest.java | 25 ++++++++++++++++++- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index e2c657b0c3..2d4964cc0f 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -574,12 +574,11 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder { do { char firstChar = line.charAt(0); if (name != null && (firstChar == ' ' || firstChar == '\t')) { + //please do not make one line from below code + //as it breaks +XX:OptimizeStringConcat optimization String trimmedLine = line.toString().trim(); - StringBuilder buf = new StringBuilder(value.length() + trimmedLine.length() + 1); - buf.append(value) - .append(' ') - .append(trimmedLine); - value = buf.toString(); + String valueStr = String.valueOf(value); + value = valueStr + ' ' + trimmedLine; } else { if (name != null) { headers.add(name, value); @@ -641,14 +640,11 @@ public abstract class HttpObjectDecoder extends ByteToMessageDecoder { List current = trailer.trailingHeaders().getAll(lastHeader); if (!current.isEmpty()) { int lastPos = current.size() - 1; + //please do not make one line from below code + //as it breaks +XX:OptimizeStringConcat optimization String lineTrimmed = line.toString().trim(); - CharSequence currentLastPos = current.get(lastPos); - StringBuilder b = new StringBuilder(currentLastPos.length() + lineTrimmed.length()); - b.append(currentLastPos) - .append(lineTrimmed); - current.set(lastPos, b.toString()); - } else { - // Content-Length, Transfer-Encoding, or Trailer + String currentLastPos = current.get(lastPos); + current.set(lastPos, currentLastPos + lineTrimmed); } } else { splitHeader(line); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java index 4689e64a97..b12ab2d69e 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java @@ -174,6 +174,29 @@ public class HttpRequestDecoderTest { assertNull(channel.readInbound()); } + @Test + public void testMultiLineHeader() { + EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); + String crlf = "\r\n"; + String request = "GET /some/path HTTP/1.1" + crlf + + "Host: localhost" + crlf + + "MyTestHeader: part1" + crlf + + " newLinePart2" + crlf + + "MyTestHeader2: part21" + crlf + + "\t newLinePart22" + + crlf + crlf; + assertTrue(channel.writeInbound(Unpooled.copiedBuffer(request, CharsetUtil.US_ASCII))); + HttpRequest req = channel.readInbound(); + assertEquals("part1 newLinePart2", req.headers().get(of("MyTestHeader"))); + assertEquals("part21 newLinePart22", req.headers().get(of("MyTestHeader2"))); + + LastHttpContent c = channel.readInbound(); + c.release(); + + assertFalse(channel.finish()); + assertNull(channel.readInbound()); + } + @Test public void testEmptyHeaderValue() { EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); @@ -181,7 +204,7 @@ public class HttpRequestDecoderTest { String request = "GET /some/path HTTP/1.1" + crlf + "Host: localhost" + crlf + "EmptyHeader:" + crlf + crlf; - channel.writeInbound(Unpooled.wrappedBuffer(request.getBytes(CharsetUtil.US_ASCII))); + channel.writeInbound(Unpooled.copiedBuffer(request, CharsetUtil.US_ASCII)); HttpRequest req = channel.readInbound(); assertEquals("", req.headers().get(of("EmptyHeader"))); }