diff options
-rw-r--r-- | luni/src/main/java/libcore/net/http/ResponseUtils.java | 90 | ||||
-rw-r--r-- | luni/src/test/java/libcore/net/http/ResponseUtilsTest.java | 52 |
2 files changed, 142 insertions, 0 deletions
diff --git a/luni/src/main/java/libcore/net/http/ResponseUtils.java b/luni/src/main/java/libcore/net/http/ResponseUtils.java new file mode 100644 index 0000000..c892b53 --- /dev/null +++ b/luni/src/main/java/libcore/net/http/ResponseUtils.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.net.http; + +import java.nio.charset.Charset; +import java.nio.charset.IllegalCharsetNameException; +import java.nio.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * @hide + */ +public class ResponseUtils { + /** + * Returns the response charset of a HTTP response based on the {@code Content-Type} of + * the response (see RFC 7230). If the {@code Content-Type} header is missing or invalid, + * the response is assumed to be encoded as {@code UTF-8}. Note that a charset usually + * makes sense only for {@code "text/plain"} and other "text based" responses. + * + * @throws IllegalCharsetNameException if the response specified charset is illegal. + * @throws UnsupportedCharsetException if the response specified charset is unsupported. + */ + public static Charset responseCharset(String contentTypeHeader) + throws IllegalCharsetNameException, UnsupportedCharsetException { + Charset responseCharset = StandardCharsets.UTF_8; + if (contentTypeHeader != null) { + Map<String, String> contentTypeParams = parseContentTypeParameters(contentTypeHeader); + String charsetParameter = contentTypeParams.get("charset"); + if (charsetParameter != null) { + responseCharset = Charset.forName(charsetParameter); + } + } + + return responseCharset; + } + + /** + * Parse content-type parameters. The format of this header is roughly : + * {@code type/subtype; param1=value1; param2=value2 ...} where each of the + * parameters are optional. Parsing is lenient, malformed parameters are ignored. + * + * Parameter keys & values are trimmed of whitespace and keys are converted to + * lower case. + */ + private static Map<String, String> parseContentTypeParameters(String contentTypeHeader) { + Map<String, String> parameters = Collections.EMPTY_MAP; + + String[] fields = contentTypeHeader.split(";"); + if (fields.length > 1) { + parameters = new HashMap<>(); + // Ignore the first element in the array (the type/subtype). + for (int i = 1; i < fields.length; ++i) { + final String parameter = fields[i]; + if (!parameter.isEmpty()) { + final String[] components = parameter.split("="); + if (components.length != 2) { + continue; + } + + final String key = components[0].trim().toLowerCase(); + final String value = components[1].trim(); + if (key.isEmpty() || value.isEmpty()) { + continue; + } + + parameters.put(key, value); + } + } + } + + return parameters; + } +} diff --git a/luni/src/test/java/libcore/net/http/ResponseUtilsTest.java b/luni/src/test/java/libcore/net/http/ResponseUtilsTest.java new file mode 100644 index 0000000..16745ee --- /dev/null +++ b/luni/src/test/java/libcore/net/http/ResponseUtilsTest.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package libcore.net.http; + +import java.nio.charset.StandardCharsets; +import java.nio.charset.UnsupportedCharsetException; +import junit.framework.TestCase; +import static libcore.net.http.ResponseUtils.responseCharset; + +public class ResponseUtilsTest extends TestCase { + public void test_responseCharset_missing() { + assertEquals(StandardCharsets.UTF_8, responseCharset(null)); + assertEquals(StandardCharsets.UTF_8, responseCharset("text/plain")); + assertEquals(StandardCharsets.UTF_8, responseCharset("text/plain;foo=bar;baz=bal")); + assertEquals(StandardCharsets.UTF_8, responseCharset("text/plain;charset=")); + } + + public void test_responseCharset_valid() { + assertEquals(StandardCharsets.ISO_8859_1, + responseCharset("text/plain;charset=ISO-8859-1")); + assertEquals(StandardCharsets.ISO_8859_1, + responseCharset("text/plain;CHARSET=ISO-8859-1")); + assertEquals(StandardCharsets.ISO_8859_1, + responseCharset("text/plain; charset = ISO-8859-1")); + assertEquals(StandardCharsets.ISO_8859_1, + responseCharset("text/plain; foo=bar;baz=bag;charset=ISO-8859-1")); + assertEquals(StandardCharsets.ISO_8859_1, + responseCharset("text/plain;charset=ISO-8859-1;;==,==")); + } + + public void test_responseCharset_invalid() { + try { + responseCharset("text/plain;charset=unsupportedCharset"); + fail(); + } catch (UnsupportedCharsetException expected) { + } + } +} |