Helper method to get mime-type from Content-Type header of HttpMessage

This commit is contained in:
Dmitry Spikhalskiy 2016-02-24 03:24:08 +03:00 committed by Norman Maurer
parent 4b5b230802
commit 0d3eda38e1
4 changed files with 123 additions and 2 deletions

View File

@ -40,6 +40,7 @@ public final class HttpUtil {
@Deprecated @Deprecated
static final EmptyHttpHeaders EMPTY_HEADERS = new EmptyHttpHeaders(); static final EmptyHttpHeaders EMPTY_HEADERS = new EmptyHttpHeaders();
private static final AsciiString CHARSET_EQUALS = AsciiString.of(HttpHeaderValues.CHARSET + "="); private static final AsciiString CHARSET_EQUALS = AsciiString.of(HttpHeaderValues.CHARSET + "=");
private static final AsciiString SEMICOLON = AsciiString.of(";");
private HttpUtil() { } 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" * 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 * 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) { public static CharSequence getCharsetAsString(HttpMessage message) {
CharSequence contentTypeValue = message.headers().get(HttpHeaderNames.CONTENT_TYPE); CharSequence contentTypeValue = message.headers().get(HttpHeaderNames.CONTENT_TYPE);
@ -381,6 +383,29 @@ public final class HttpUtil {
return null; 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
* <p/>
* "content-type: text/html; charset=utf-8" - "text/html" will be returned <br/>
* "content-type: text/html" - "text/html" will be returned <br/>
* "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) { static void encodeAscii0(CharSequence seq, ByteBuf buf) {
int length = seq.length(); int length = seq.length();
for (int i = 0 ; i < length; i++) { for (int i = 0 ; i < length; i++) {

View File

@ -88,4 +88,16 @@ public class HttpUtilTest {
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTFFF"); message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTFFF");
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message, StandardCharsets.UTF_8)); 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));
}
} }

View File

@ -713,6 +713,34 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
} }
} }
/**
* 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 * 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. * and moves towards the beginning of this string.
@ -1741,6 +1769,38 @@ public final class AsciiString implements CharSequence, Comparable<CharSequence>
return INDEX_NOT_FOUND; return INDEX_NOT_FOUND;
} }
/**
* <p>Finds the first index in the {@code CharSequence} that matches the
* specified character.</p>
*
* @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) { private static boolean equalsIgnoreCase(byte a, byte b) {
return a == b || toLowerCase(a) == toLowerCase(b); return a == b || toLowerCase(a) == toLowerCase(b);
} }

View File

@ -290,4 +290,28 @@ public class AsciiStringCharacterTest {
assertEquals("abc", new AsciiString("abc ").trim().toString()); assertEquals("abc", new AsciiString("abc ").trim().toString());
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));
}
} }