Expose CharSequence version of HttpUtil#getMimeType and HttpUtil#getCharset

Motivation:

It would be more flexible to make getCharset and getMimeType code usable not only for HttpMessage entity but just for any CharSequence. This will improve usability in general purpose code and will help to avoid multiple fetching of ContentType header from a message. It could be done in an external code once and CharSequence method versions could be applied.

Modification:
Expose HttpUtil#getMimeType, HttpUtil#getCharsetAsString, HttpUtil#getCharset versions which works with CharSequence. New methods are reused in the old ones which work with HttpMessage entity.

Result:

More flexible methods set with a good code reusing.
This commit is contained in:
Dmitry Spikhalskiy 2016-11-15 22:24:07 +03:00 committed by Norman Maurer
parent 02a2738cd2
commit 464ae9fb7a
2 changed files with 140 additions and 32 deletions

View File

@ -356,6 +356,7 @@ public final class HttpUtil {
/**
* Fetch charset from message's Content-Type header.
*
* @param message entity to fetch Content-Type header from
* @return the charset from message's Content-Type header or {@link io.netty.util.CharsetUtil#ISO_8859_1}
* if charset is not presented or unparsable
*/
@ -363,18 +364,56 @@ public final class HttpUtil {
return getCharset(message, CharsetUtil.ISO_8859_1);
}
/**
* Fetch charset from Content-Type header value.
*
* @param contentTypeValue Content-Type header value to parse
* @return the charset from message's Content-Type header or {@link io.netty.util.CharsetUtil#ISO_8859_1}
* if charset is not presented or unparsable
*/
public static Charset getCharset(CharSequence contentTypeValue) {
if (contentTypeValue != null) {
return getCharset(contentTypeValue, CharsetUtil.ISO_8859_1);
} else {
return CharsetUtil.ISO_8859_1;
}
}
/**
* Fetch charset from message's Content-Type header.
*
* @param message entity to fetch Content-Type header from
* @param defaultCharset result to use in case of empty, incorrect or doesn't conain required part header value
* @return the charset from message's Content-Type header or {@code defaultCharset}
* if charset is not presented or unparsable
*/
public static Charset getCharset(HttpMessage message, Charset defaultCharset) {
CharSequence charsetCharSequence = getCharsetAsSequence(message);
if (charsetCharSequence != null) {
try {
return Charset.forName(charsetCharSequence.toString());
} catch (UnsupportedCharsetException unsupportedException) {
CharSequence contentTypeValue = message.headers().get(HttpHeaderNames.CONTENT_TYPE);
if (contentTypeValue != null) {
return getCharset(contentTypeValue, defaultCharset);
} else {
return defaultCharset;
}
}
/**
* Fetch charset from Content-Type header value.
*
* @param contentTypeValue Content-Type header value to parse
* @param defaultCharset result to use in case of empty, incorrect or doesn't contain required part header value
* @return the charset from message's Content-Type header or {@code defaultCharset}
* if charset is not presented or unparsable
*/
public static Charset getCharset(CharSequence contentTypeValue, Charset defaultCharset) {
if (contentTypeValue != null) {
CharSequence charsetCharSequence = getCharsetAsSequence(contentTypeValue);
if (charsetCharSequence != null) {
try {
return Charset.forName(charsetCharSequence.toString());
} catch (UnsupportedCharsetException unsupportedException) {
return defaultCharset;
}
} else {
return defaultCharset;
}
} else {
@ -388,6 +427,7 @@ public final class HttpUtil {
* 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
*
* @param message entity to fetch Content-Type header from
* @return the {@code CharSequence} with charset from message's Content-Type header
* or {@code null} if charset is not presented
* @deprecated use {@link #getCharsetAsSequence(HttpMessage)}
@ -409,12 +449,32 @@ public final class HttpUtil {
public static CharSequence getCharsetAsSequence(HttpMessage message) {
CharSequence contentTypeValue = message.headers().get(HttpHeaderNames.CONTENT_TYPE);
if (contentTypeValue != null) {
int indexOfCharset = AsciiString.indexOfIgnoreCaseAscii(contentTypeValue, CHARSET_EQUALS, 0);
if (indexOfCharset != AsciiString.INDEX_NOT_FOUND) {
int indexOfEncoding = indexOfCharset + CHARSET_EQUALS.length();
if (indexOfEncoding < contentTypeValue.length()) {
return contentTypeValue.subSequence(indexOfEncoding, contentTypeValue.length());
}
return getCharsetAsSequence(contentTypeValue);
} else {
return null;
}
}
/**
* Fetch charset from Content-Type header value 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
*
* @param contentTypeValue Content-Type header value to parse
* @return the {@code CharSequence} with charset from message's Content-Type header
* or {@code null} if charset is not presented
* @throws NullPointerException in case if {@code contentTypeValue == null}
*/
public static CharSequence getCharsetAsSequence(CharSequence contentTypeValue) {
if (contentTypeValue == null) {
throw new NullPointerException("contentTypeValue");
}
int indexOfCharset = AsciiString.indexOfIgnoreCaseAscii(contentTypeValue, CHARSET_EQUALS, 0);
if (indexOfCharset != AsciiString.INDEX_NOT_FOUND) {
int indexOfEncoding = indexOfCharset + CHARSET_EQUALS.length();
if (indexOfEncoding < contentTypeValue.length()) {
return contentTypeValue.subSequence(indexOfEncoding, contentTypeValue.length());
}
}
return null;
@ -423,6 +483,7 @@ public final class HttpUtil {
/**
* Fetch MIME type part from message's Content-Type header as a char sequence.
*
* @param message entity to fetch Content-Type header from
* @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/>
@ -433,14 +494,35 @@ public final class HttpUtil {
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 getMimeType(contentTypeValue);
} else {
return null;
}
}
/**
* Fetch MIME type part from Content-Type header value as a char sequence.
*
* @param contentTypeValue Content-Type header value to parse
* @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: empty header - {@code null} we be returned
* @throws NullPointerException in case if {@code contentTypeValue == null}
*/
public static CharSequence getMimeType(CharSequence contentTypeValue) {
if (contentTypeValue == null) {
throw new NullPointerException("contentTypeValue");
}
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) {

View File

@ -19,6 +19,7 @@ import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -56,51 +57,76 @@ public class HttpUtilTest {
}
@Test
public void testGetCharsetAsRawString() {
public void testGetCharsetAsRawCharSequence() {
String QUOTES_CHARSET_CONTENT_TYPE = "text/html; charset=\"utf8\"";
String SIMPLE_CONTENT_TYPE = "text/html";
HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=\"utf8\"");
message.headers().set(HttpHeaderNames.CONTENT_TYPE, QUOTES_CHARSET_CONTENT_TYPE);
assertEquals("\"utf8\"", HttpUtil.getCharsetAsSequence(message));
assertEquals("\"utf8\"", HttpUtil.getCharsetAsSequence(QUOTES_CHARSET_CONTENT_TYPE));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
assertNull(HttpUtil.getCharsetAsSequence(message));
assertNull(HttpUtil.getCharsetAsSequence(SIMPLE_CONTENT_TYPE));
}
@Test
public void testGetCharset() {
HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8");
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message));
String NORMAL_CONTENT_TYPE = "text/html; charset=utf-8";
String UPPER_CASE_NORMAL_CONTENT_TYPE = "TEXT/HTML; CHARSET=UTF-8";
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "TEXT/HTML; CHARSET=UTF-8");
HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
message.headers().set(HttpHeaderNames.CONTENT_TYPE, NORMAL_CONTENT_TYPE);
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message));
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(NORMAL_CONTENT_TYPE));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, UPPER_CASE_NORMAL_CONTENT_TYPE);
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message));
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(UPPER_CASE_NORMAL_CONTENT_TYPE));
}
@Test
public void testGetCharset_defaultValue() {
final String SIMPLE_CONTENT_TYPE = "text/html";
final String CONTENT_TYPE_WITH_INCORRECT_CHARSET = "text/html; charset=UTFFF";
HttpMessage message = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
message.headers().set(HttpHeaderNames.CONTENT_TYPE, SIMPLE_CONTENT_TYPE);
assertEquals(CharsetUtil.ISO_8859_1, HttpUtil.getCharset(message));
assertEquals(CharsetUtil.ISO_8859_1, HttpUtil.getCharset(SIMPLE_CONTENT_TYPE));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html");
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message, CharsetUtil.UTF_8));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, SIMPLE_CONTENT_TYPE);
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message, StandardCharsets.UTF_8));
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(SIMPLE_CONTENT_TYPE, StandardCharsets.UTF_8));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTFFF");
message.headers().set(HttpHeaderNames.CONTENT_TYPE, CONTENT_TYPE_WITH_INCORRECT_CHARSET);
assertEquals(CharsetUtil.ISO_8859_1, HttpUtil.getCharset(message));
assertEquals(CharsetUtil.ISO_8859_1, HttpUtil.getCharset(CONTENT_TYPE_WITH_INCORRECT_CHARSET));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTFFF");
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message, CharsetUtil.UTF_8));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, CONTENT_TYPE_WITH_INCORRECT_CHARSET);
assertEquals(CharsetUtil.UTF_8, HttpUtil.getCharset(message, StandardCharsets.UTF_8));
assertEquals(CharsetUtil.UTF_8,
HttpUtil.getCharset(CONTENT_TYPE_WITH_INCORRECT_CHARSET, StandardCharsets.UTF_8));
}
@Test
public void testGetMimeType() {
final String SIMPLE_CONTENT_TYPE = "text/html";
final String NORMAL_CONTENT_TYPE = "text/html; charset=utf-8";
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");
assertNull(HttpUtil.getMimeType(""));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, SIMPLE_CONTENT_TYPE);
assertEquals("text/html", HttpUtil.getMimeType(message));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=utf-8");
assertEquals("text/html", HttpUtil.getMimeType(SIMPLE_CONTENT_TYPE));
message.headers().set(HttpHeaderNames.CONTENT_TYPE, NORMAL_CONTENT_TYPE);
assertEquals("text/html", HttpUtil.getMimeType(message));
assertEquals("text/html", HttpUtil.getMimeType(NORMAL_CONTENT_TYPE));
}
@Test