From 0d3eda38e15582d1dac05920787f1c9f3a9f781e Mon Sep 17 00:00:00 2001 From: Dmitry Spikhalskiy Date: Wed, 24 Feb 2016 03:24:08 +0300 Subject: [PATCH] Helper method to get mime-type from Content-Type header of HttpMessage --- .../io/netty/handler/codec/http/HttpUtil.java | 29 ++++++++- .../handler/codec/http/HttpUtilTest.java | 12 ++++ .../main/java/io/netty/util/AsciiString.java | 60 +++++++++++++++++++ .../netty/util/AsciiStringCharacterTest.java | 24 ++++++++ 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpUtil.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpUtil.java index 1755b25bbe..d221095cfb 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpUtil.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpUtil.java @@ -40,6 +40,7 @@ public final class HttpUtil { @Deprecated static final EmptyHttpHeaders EMPTY_HEADERS = new EmptyHttpHeaders(); private static final AsciiString CHARSET_EQUALS = AsciiString.of(HttpHeaderValues.CHARSET + "="); + private static final AsciiString SEMICOLON = AsciiString.of(";"); private HttpUtil() { } @@ -360,12 +361,13 @@ public final class HttpUtil { } /** - * Fetch charset string from message's Content-Type header. + * Fetch charset from message's Content-Type header as a char sequence. * * A lot of sites/possibly clients have charset="CHARSET", for example charset="utf-8". Or "utf8" instead of "utf-8" * This is not according to standard, but this method provide an ability to catch desired mistakes manually in code * - * @return the charset string from message's Content-Type header or {@code null} if charset is not presented + * @return the {@code CharSequence} with charset from message's Content-Type header + * or {@code null} if charset is not presented */ public static CharSequence getCharsetAsString(HttpMessage message) { CharSequence contentTypeValue = message.headers().get(HttpHeaderNames.CONTENT_TYPE); @@ -381,6 +383,29 @@ public final class HttpUtil { return null; } + /** + * Fetch MIME type part from message's Content-Type header as a char sequence. + * + * @return the MIME type as a {@code CharSequence} from message's Content-Type header + * or {@code null} if content-type header or MIME type part of this header are not presented + *

+ * "content-type: text/html; charset=utf-8" - "text/html" will be returned
+ * "content-type: text/html" - "text/html" will be returned
+ * "content-type: " or no header - {@code null} we be returned + */ + public static CharSequence getMimeType(HttpMessage message) { + CharSequence contentTypeValue = message.headers().get(HttpHeaderNames.CONTENT_TYPE); + if (contentTypeValue != null) { + int indexOfSemicolon = AsciiString.indexOfIgnoreCaseAscii(contentTypeValue, SEMICOLON, 0); + if (indexOfSemicolon != AsciiString.INDEX_NOT_FOUND) { + return contentTypeValue.subSequence(0, indexOfSemicolon); + } else { + return contentTypeValue.length() > 0 ? contentTypeValue : null; + } + } + return null; + } + static void encodeAscii0(CharSequence seq, ByteBuf buf) { int length = seq.length(); for (int i = 0 ; i < length; i++) { diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpUtilTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpUtilTest.java index ce47340277..1e9615ce8f 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpUtilTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpUtilTest.java @@ -88,4 +88,16 @@ public class HttpUtilTest { message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTFFF"); assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message, StandardCharsets.UTF_8)); } + + @Test + public void testGetMimeType() { + HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK); + assertNull(HttpUtil.getMimeType(message)); + message.headers().set(HttpHeaderNames.CONTENT_TYPE, ""); + assertNull(HttpUtil.getMimeType(message)); + message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html"); + assertEquals("text/html", HttpUtil.getMimeType(message)); + message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8"); + assertEquals("text/html", HttpUtil.getMimeType(message)); + } } diff --git a/common/src/main/java/io/netty/util/AsciiString.java b/common/src/main/java/io/netty/util/AsciiString.java index 31adacd62f..8431a7c095 100644 --- a/common/src/main/java/io/netty/util/AsciiString.java +++ b/common/src/main/java/io/netty/util/AsciiString.java @@ -713,6 +713,34 @@ public final class AsciiString implements CharSequence, Comparable } } + /** + * Searches in this string for the index of the specified char {@code ch}. + * The search for the char starts at the specified offset {@code start} and moves towards the end of this string. + * + * @param ch the char to find. + * @param start the starting offset. + * @return the index of the first occurrence of the specified char {@code ch} in this string, + * -1 if found no occurrence. + */ + public int indexOf(char ch, int start) { + if (start < 0) { + start = 0; + } + + final int thisLen = length(); + + if (ch > MAX_CHAR_VALUE) { + return -1; + } + + try { + return forEachByte(start, thisLen - start, new IndexOfProcessor((byte) ch)); + } catch (Exception e) { + PlatformDependent.throwException(e); + return -1; + } + } + /** * Searches in this string for the last index of the specified string. The search for the string starts at the end * and moves towards the beginning of this string. @@ -1741,6 +1769,38 @@ public final class AsciiString implements CharSequence, Comparable return INDEX_NOT_FOUND; } + /** + *

Finds the first index in the {@code CharSequence} that matches the + * specified character.

+ * + * @param cs the {@code CharSequence} to be processed, not null + * @param searchChar the char to be searched for + * @param start the start index, negative starts at the string start + * @return the index where the search char was found, + * -1 if char {@code searchChar} is not found or {@code cs == null} + */ + //----------------------------------------------------------------------- + public static int indexOf(final CharSequence cs, final char searchChar, int start) { + if (cs instanceof String) { + return ((String) cs).indexOf(searchChar, start); + } else if (cs instanceof AsciiString) { + return ((AsciiString) cs).indexOf(searchChar, start); + } + if (cs == null) { + return INDEX_NOT_FOUND; + } + final int sz = cs.length(); + if (start < 0) { + start = 0; + } + for (int i = start; i < sz; i++) { + if (cs.charAt(i) == searchChar) { + return i; + } + } + return INDEX_NOT_FOUND; + } + private static boolean equalsIgnoreCase(byte a, byte b) { return a == b || toLowerCase(a) == toLowerCase(b); } diff --git a/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java b/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java index 5e79662341..8914367890 100644 --- a/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java +++ b/common/src/test/java/io/netty/util/AsciiStringCharacterTest.java @@ -290,4 +290,28 @@ public class AsciiStringCharacterTest { assertEquals("abc", new AsciiString("abc ").trim().toString()); assertEquals("abc", new AsciiString(" abc ").trim().toString()); } + + @Test + public void testIndexOfChar() { + assertEquals(-1, AsciiString.indexOf(null, 'a', 0)); + assertEquals(-1, AsciiString.of("").indexOf('a', 0)); + assertEquals(-1, AsciiString.of("abc").indexOf('d', 0)); + assertEquals(-1, AsciiString.of("aabaabaa").indexOf('A', 0)); + assertEquals(0, AsciiString.of("aabaabaa").indexOf('a', 0)); + assertEquals(1, AsciiString.of("aabaabaa").indexOf('a', 1)); + assertEquals(3, AsciiString.of("aabaabaa").indexOf('a', 2)); + assertEquals(3, AsciiString.of("aabdabaa").indexOf('d', 1)); + } + + @Test + public void testStaticIndexOfChar() { + assertEquals(-1, AsciiString.indexOf(null, 'a', 0)); + assertEquals(-1, AsciiString.indexOf("", 'a', 0)); + assertEquals(-1, AsciiString.indexOf("abc", 'd', 0)); + assertEquals(-1, AsciiString.indexOf("aabaabaa", 'A', 0)); + assertEquals(0, AsciiString.indexOf("aabaabaa", 'a', 0)); + assertEquals(1, AsciiString.indexOf("aabaabaa", 'a', 1)); + assertEquals(3, AsciiString.indexOf("aabaabaa", 'a', 2)); + assertEquals(3, AsciiString.indexOf("aabdabaa", 'd', 1)); + } }