1
0
mirror of https://github.com/square/okhttp.git synced 2025-07-31 05:04:26 +03:00

Add parse overload which fails on invalid inputs

This commit is contained in:
Jake Wharton
2018-07-05 22:09:40 -04:00
parent d45f517f1f
commit 36f4fd04f7
24 changed files with 191 additions and 124 deletions

View File

@ -660,7 +660,7 @@ public class JavaApiConverterTest {
}
private static RequestBody createRequestBody(String bodyText) {
return RequestBody.create(MediaType.parse("text/plain"), bodyText);
return RequestBody.create(MediaType.get("text/plain"), bodyText);
}
private static ResponseBody createResponseBody(String bodyText) {
@ -668,7 +668,7 @@ public class JavaApiConverterTest {
final long contentLength = source.size();
return new ResponseBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain; charset=utf-8");
return MediaType.get("text/plain; charset=utf-8");
}
@Override public long contentLength() {

View File

@ -8,7 +8,7 @@ import org.apache.http.HttpEntity;
/** Adapts an {@link HttpEntity} to OkHttp's {@link RequestBody}. */
final class HttpEntityBody extends RequestBody {
private static final MediaType DEFAULT_MEDIA_TYPE = MediaType.parse("application/octet-stream");
private static final MediaType DEFAULT_MEDIA_TYPE = MediaType.get("application/octet-stream");
private final HttpEntity entity;
private final MediaType mediaType;

View File

@ -53,8 +53,8 @@ import okio.ByteString;
* Until then, expect API and behavior changes when you update your OkHttp dependency.</strong>
*/
public class DnsOverHttps implements Dns {
public static final MediaType DNS_MESSAGE = MediaType.parse("application/dns-message");
public static final MediaType UDPWIREFORMAT = MediaType.parse("application/dns-udpwireformat");
public static final MediaType DNS_MESSAGE = MediaType.get("application/dns-message");
public static final MediaType UDPWIREFORMAT = MediaType.get("application/dns-udpwireformat");
public static final int MAX_RESPONSE_SIZE = 64 * 1024;
private final OkHttpClient client;
private final HttpUrl url;

View File

@ -53,7 +53,7 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;
public final class HttpLoggingInterceptorTest {
private static final MediaType PLAIN = MediaType.parse("text/plain; charset=utf-8");
private static final MediaType PLAIN = MediaType.get("text/plain; charset=utf-8");
@Rule public final MockWebServer server = new MockWebServer();

View File

@ -774,7 +774,7 @@ public final class CacheTest {
private RequestBody requestBodyOrNull(String requestMethod) {
return (requestMethod.equals("POST") || requestMethod.equals("PUT"))
? RequestBody.create(MediaType.parse("text/plain"), "foo")
? RequestBody.create(MediaType.get("text/plain"), "foo")
: null;
}
@ -862,7 +862,7 @@ public final class CacheTest {
Request request = new Request.Builder()
.url(url)
.put(RequestBody.create(MediaType.parse("text/plain"), "foo"))
.put(RequestBody.create(MediaType.get("text/plain"), "foo"))
.build();
Response invalidate = client.newCall(request).execute();
assertEquals("", invalidate.body().string());

View File

@ -206,7 +206,7 @@ public final class CallTest {
server.enqueue(new MockResponse());
try {
new Request.Builder().method("GET", RequestBody.create(MediaType.parse("text/plain"), "abc"));
new Request.Builder().method("GET", RequestBody.create(MediaType.get("text/plain"), "abc"));
fail();
} catch (IllegalArgumentException expected) {
}
@ -300,7 +300,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "def"))
.post(RequestBody.create(MediaType.get("text/plain"), "def"))
.build();
executeSynchronously(request)
@ -501,7 +501,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.method("DELETE", RequestBody.create(MediaType.parse("text/plain"), "def"))
.method("DELETE", RequestBody.create(MediaType.get("text/plain"), "def"))
.build();
executeSynchronously(request)
@ -518,7 +518,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.put(RequestBody.create(MediaType.parse("text/plain"), "def"))
.put(RequestBody.create(MediaType.get("text/plain"), "def"))
.build();
executeSynchronously(request)
@ -547,7 +547,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.patch(RequestBody.create(MediaType.parse("text/plain"), "def"))
.patch(RequestBody.create(MediaType.get("text/plain"), "def"))
.build();
executeSynchronously(request)
@ -576,7 +576,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.method("CUSTOM", RequestBody.create(MediaType.parse("text/plain"), "def"))
.method("CUSTOM", RequestBody.create(MediaType.get("text/plain"), "def"))
.build();
executeSynchronously(request)
@ -937,7 +937,7 @@ public final class CallTest {
// Call 1: set a deadline on the request body.
RequestBody requestBody1 = new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain");
return MediaType.get("text/plain");
}
@Override public void writeTo(BufferedSink sink) throws IOException {
@ -955,7 +955,7 @@ public final class CallTest {
// Call 2: check for the absence of a deadline on the request body.
RequestBody requestBody2 = new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain");
return MediaType.get("text/plain");
}
@Override public void writeTo(BufferedSink sink) throws IOException {
@ -1272,7 +1272,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "def"))
.post(RequestBody.create(MediaType.get("text/plain"), "def"))
.build();
client.newCall(request).enqueue(callback);
@ -1298,7 +1298,7 @@ public final class CallTest {
Request request2 = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "body!"))
.post(RequestBody.create(MediaType.get("text/plain"), "body!"))
.build();
Response response2 = client.newCall(request2).execute();
assertEquals("def", response2.body().string());
@ -1614,7 +1614,7 @@ public final class CallTest {
Response response = client.newCall(new Request.Builder()
.url(server.url("/page1"))
.post(RequestBody.create(MediaType.parse("text/plain"), "Request Body"))
.post(RequestBody.create(MediaType.get("text/plain"), "Request Body"))
.build()).execute();
assertEquals("Page 2", response.body().string());
@ -1668,7 +1668,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "Hello"))
.post(RequestBody.create(MediaType.get("text/plain"), "Hello"))
.build();
Response response = client.newCall(request).execute();
@ -1777,7 +1777,7 @@ public final class CallTest {
// when
Response response = client.newCall(new Request.Builder()
.url(server.url("/page1"))
.method("PROPFIND", RequestBody.create(MediaType.parse("text/plain"), "Request Body"))
.method("PROPFIND", RequestBody.create(MediaType.get("text/plain"), "Request Body"))
.build()).execute();
// then
@ -2408,7 +2408,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.header("Expect", "100-continue")
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build();
executeSynchronously(request)
@ -2424,7 +2424,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.header("Expect", "100-continue")
.post(RequestBody.create(MediaType.parse("text/plain"), ""))
.post(RequestBody.create(MediaType.get("text/plain"), ""))
.build();
executeSynchronously(request)
@ -2448,7 +2448,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.header("Expect", "100-continue")
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build();
Call call = client.newCall(request);
@ -2473,7 +2473,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build();
executeSynchronously(request)
@ -2499,7 +2499,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build();
Call call = client.newCall(request);
@ -2526,7 +2526,7 @@ public final class CallTest {
executeSynchronously(new Request.Builder()
.url(server.url("/"))
.header("Expect", "100-continue")
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build());
executeSynchronously(new Request.Builder()
.url(server.url("/"))
@ -2548,7 +2548,7 @@ public final class CallTest {
executeSynchronously(new Request.Builder()
.url(server.url("/"))
.header("Expect", "100-continue")
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build());
executeSynchronously(new Request.Builder()
.url(server.url("/"))
@ -2567,7 +2567,7 @@ public final class CallTest {
executeSynchronously(new Request.Builder()
.url(server.url("/"))
.header("Expect", "100-continue")
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build());
executeSynchronously(new Request.Builder()
.url(server.url("/"))
@ -2972,7 +2972,7 @@ public final class CallTest {
Request request = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "abc"))
.post(RequestBody.create(MediaType.get("text/plain"), "abc"))
.build();
executeSynchronously(request);
@ -3064,7 +3064,7 @@ public final class CallTest {
return new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain; charset=utf-8");
return MediaType.get("text/plain; charset=utf-8");
}
@Override public long contentLength() throws IOException {

View File

@ -191,7 +191,7 @@ public final class ConnectionReuseTest {
Request requestB = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), "b"))
.post(RequestBody.create(MediaType.get("text/plain"), "b"))
.build();
Response responseB = client.newCall(requestB).execute();
assertEquals("b", responseB.body().string());

View File

@ -970,7 +970,7 @@ public final class EventListenerTest {
// Stream a 8 MiB body so the disconnect will happen before the server has read everything.
RequestBody requestBody = new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain");
return MediaType.get("text/plain");
}
@Override public long contentLength() {
@ -1005,26 +1005,26 @@ public final class EventListenerTest {
@Test public void requestBodySuccessHttp1OverHttps() throws IOException {
enableTlsWithTunnel(false);
server.setProtocols(Arrays.asList(Protocol.HTTP_1_1));
requestBodySuccess(RequestBody.create(MediaType.parse("text/plain"), "Hello"), equalTo(5L),
requestBodySuccess(RequestBody.create(MediaType.get("text/plain"), "Hello"), equalTo(5L),
equalTo(19L));
}
@Test public void requestBodySuccessHttp2OverHttps() throws IOException {
enableTlsWithTunnel(false);
server.setProtocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1));
requestBodySuccess(RequestBody.create(MediaType.parse("text/plain"), "Hello"), equalTo(5L),
requestBodySuccess(RequestBody.create(MediaType.get("text/plain"), "Hello"), equalTo(5L),
equalTo(19L));
}
@Test public void requestBodySuccessHttp() throws IOException {
requestBodySuccess(RequestBody.create(MediaType.parse("text/plain"), "Hello"), equalTo(5L),
requestBodySuccess(RequestBody.create(MediaType.get("text/plain"), "Hello"), equalTo(5L),
equalTo(19L));
}
@Test public void requestBodySuccessStreaming() throws IOException {
RequestBody requestBody = new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain");
return MediaType.get("text/plain");
}
@Override public void writeTo(BufferedSink sink) throws IOException {
@ -1037,7 +1037,7 @@ public final class EventListenerTest {
}
@Test public void requestBodySuccessEmpty() throws IOException {
requestBodySuccess(RequestBody.create(MediaType.parse("text/plain"), ""), equalTo(0L),
requestBodySuccess(RequestBody.create(MediaType.get("text/plain"), ""), equalTo(0L),
equalTo(19L));
}

View File

@ -67,7 +67,7 @@ public final class InterceptorTest {
.protocol(Protocol.HTTP_1_1)
.code(200)
.message("Intercepted!")
.body(ResponseBody.create(MediaType.parse("text/plain; charset=utf-8"), "abc"))
.body(ResponseBody.create(MediaType.get("text/plain; charset=utf-8"), "abc"))
.build();
client = client.newBuilder()
@ -91,7 +91,7 @@ public final class InterceptorTest {
.protocol(Protocol.HTTP_1_1)
.code(200)
.message("Intercepted!")
.body(ResponseBody.create(MediaType.parse("text/plain; charset=utf-8"), "abc"))
.body(ResponseBody.create(MediaType.get("text/plain; charset=utf-8"), "abc"))
.build();
}
};
@ -234,7 +234,7 @@ public final class InterceptorTest {
Interceptor interceptor = new Interceptor() {
@Override public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
MediaType mediaType = MediaType.parse("text/plain");
MediaType mediaType = MediaType.get("text/plain");
RequestBody body = RequestBody.create(mediaType, "abc");
return chain.proceed(originalRequest.newBuilder()
.method("POST", body)
@ -283,7 +283,7 @@ public final class InterceptorTest {
Request request = new Request.Builder()
.url(server.url("/"))
.addHeader("Original-Header", "foo")
.method("PUT", RequestBody.create(MediaType.parse("text/plain"), "abc"))
.method("PUT", RequestBody.create(MediaType.get("text/plain"), "abc"))
.build();
client.newCall(request).execute();
@ -818,7 +818,7 @@ public final class InterceptorTest {
byte[] data = new byte[2 * 1024 * 1024]; // 2 MiB.
Request request1 = new Request.Builder()
.url(server.url("/"))
.post(RequestBody.create(MediaType.parse("text/plain"), data))
.post(RequestBody.create(MediaType.get("text/plain"), data))
.build();
Call call = client.newCall(request1);

View File

@ -17,12 +17,17 @@
package okhttp3;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;
import okhttp3.internal.Util;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
* Test MediaType API and parsing.
@ -30,16 +35,34 @@ import static org.junit.Assert.assertTrue;
* <p>This test includes tests from <a href="https://code.google.com/p/guava-libraries/">Guava's</a>
* MediaTypeTest.
*/
@RunWith(Parameterized.class)
public class MediaTypeTest {
@Parameterized.Parameters(name = "Use get = {0}")
public static Collection<Object[]> parameters() {
return Arrays.asList(
new Object[] { true },
new Object[] { false }
);
}
@Parameterized.Parameter
public boolean useGet;
private MediaType parse(String string) {
return useGet
? MediaType.get(string)
: MediaType.parse(string);
}
@Test public void testParse() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;boundary=foo;charset=utf-8");
MediaType mediaType = parse("text/plain;boundary=foo;charset=utf-8");
assertEquals("text", mediaType.type());
assertEquals("plain", mediaType.subtype());
assertEquals("UTF-8", mediaType.charset().name());
assertEquals("text/plain;boundary=foo;charset=utf-8", mediaType.toString());
assertTrue(mediaType.equals(MediaType.parse("text/plain;boundary=foo;charset=utf-8")));
assertTrue(mediaType.equals(parse("text/plain;boundary=foo;charset=utf-8")));
assertEquals(mediaType.hashCode(),
MediaType.parse("text/plain;boundary=foo;charset=utf-8").hashCode());
parse("text/plain;boundary=foo;charset=utf-8").hashCode());
}
@Test public void testValidParse() throws Exception {
@ -61,75 +84,86 @@ public class MediaTypeTest {
}
@Test public void testInvalidParse() throws Exception {
assertInvalid("");
assertInvalid("/");
assertInvalid("/");
assertInvalid("text");
assertInvalid("text/");
assertInvalid("te<t/plain");
assertInvalid("text/pl@in");
assertInvalid("text/plain; a");
assertInvalid("text/plain; a=");
assertInvalid("text/plain; a=@");
assertInvalid("text/plain; a=\"@");
assertInvalid("text/plain; a=1; b");
assertInvalid("text/plain; a=1; b=");
assertInvalid("text/plain; a=\u2025");
assertInvalid(" text/plain");
assertInvalid("te xt/plain");
assertInvalid("text /plain");
assertInvalid("text/ plain");
assertInvalid("text/pl ain");
assertInvalid("text/plain ");
assertInvalid("text/plain ; a=1");
assertInvalid("", "No subtype found for: \"\"");
assertInvalid("/", "No subtype found for: \"/\"");
assertInvalid("text", "No subtype found for: \"text\"");
assertInvalid("text/", "No subtype found for: \"text/\"");
assertInvalid("te<t/plain", "No subtype found for: \"te<t/plain\"");
assertInvalid(" text/plain", "No subtype found for: \" text/plain\"");
assertInvalid("te xt/plain", "No subtype found for: \"te xt/plain\"");
assertInvalid("text /plain", "No subtype found for: \"text /plain\"");
assertInvalid("text/ plain", "No subtype found for: \"text/ plain\"");
assertInvalid("text/pl@in",
"Parameter is not formatted correctly: \"@in\" for: \"text/pl@in\"");
assertInvalid("text/plain; a",
"Parameter is not formatted correctly: \"a\" for: \"text/plain; a\"");
assertInvalid("text/plain; a=",
"Parameter is not formatted correctly: \"a=\" for: \"text/plain; a=\"");
assertInvalid("text/plain; a=@",
"Parameter is not formatted correctly: \"a=@\" for: \"text/plain; a=@\"");
assertInvalid("text/plain; a=\"@",
"Parameter is not formatted correctly: \"a=\"@\" for: \"text/plain; a=\"@\"");
assertInvalid("text/plain; a=1; b",
"Parameter is not formatted correctly: \"b\" for: \"text/plain; a=1; b\"");
assertInvalid("text/plain; a=1; b=",
"Parameter is not formatted correctly: \"b=\" for: \"text/plain; a=1; b=\"");
assertInvalid("text/plain; a=\u2025",
"Parameter is not formatted correctly: \"a=‥\" for: \"text/plain; a=‥\"");
assertInvalid("text/pl ain",
"Parameter is not formatted correctly: \" ain\" for: \"text/pl ain\"");
assertInvalid("text/plain ",
"Parameter is not formatted correctly: \" \" for: \"text/plain \"");
assertInvalid("text/plain ; a=1",
"Parameter is not formatted correctly: \" ; a=1\" for: \"text/plain ; a=1\"");
}
@Test public void testDoubleQuotesAreSpecial() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;a=\";charset=utf-8;b=\"");
MediaType mediaType = parse("text/plain;a=\";charset=utf-8;b=\"");
assertNull(mediaType.charset());
}
@Test public void testSingleQuotesAreNotSpecial() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;a=';charset=utf-8;b='");
MediaType mediaType = parse("text/plain;a=';charset=utf-8;b='");
assertEquals("UTF-8", mediaType.charset().name());
}
@Test public void testParseWithSpecialCharacters() throws Exception {
MediaType mediaType = MediaType.parse(
"!#$%&'*+-.{|}~/!#$%&'*+-.{|}~; !#$%&'*+-.{|}~=!#$%&'*+-.{|}~");
MediaType mediaType = parse("!#$%&'*+-.{|}~/!#$%&'*+-.{|}~; !#$%&'*+-.{|}~=!#$%&'*+-.{|}~");
assertEquals("!#$%&'*+-.{|}~", mediaType.type());
assertEquals("!#$%&'*+-.{|}~", mediaType.subtype());
}
@Test public void testCharsetIsOneOfManyParameters() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;a=1;b=2;charset=utf-8;c=3");
MediaType mediaType = parse("text/plain;a=1;b=2;charset=utf-8;c=3");
assertEquals("text", mediaType.type());
assertEquals("plain", mediaType.subtype());
assertEquals("UTF-8", mediaType.charset().name());
}
@Test public void testCharsetAndQuoting() throws Exception {
MediaType mediaType = MediaType.parse(
MediaType mediaType = parse(
"text/plain;a=\";charset=us-ascii\";charset=\"utf-8\";b=\"iso-8859-1\"");
assertEquals("UTF-8", mediaType.charset().name());
}
@Test public void testDuplicatedCharsets() {
MediaType mediaType = MediaType.parse("text/plain; charset=utf-8; charset=UTF-8");
MediaType mediaType = parse("text/plain; charset=utf-8; charset=UTF-8");
assertEquals("UTF-8", mediaType.charset().name());
}
@Test public void testMultipleCharsets() {
assertNull(MediaType.parse("text/plain; charset=utf-8; charset=utf-16"));
assertInvalid("text/plain; charset=utf-8; charset=utf-16",
"Multiple charsets defined: \"utf-8\" and: \"utf-16\" for: \"text/plain; charset=utf-8; charset=utf-16\"");
}
@Test public void testIllegalCharsetName() {
MediaType mediaType = MediaType.parse("text/plain; charset=\"!@#$%^&*()\"");
MediaType mediaType = parse("text/plain; charset=\"!@#$%^&*()\"");
assertNull(mediaType.charset());
}
@Test public void testUnsupportedCharset() {
MediaType mediaType = MediaType.parse("text/plain; charset=utf-wtf");
MediaType mediaType = parse("text/plain; charset=utf-wtf");
assertNull(mediaType.charset());
}
@ -138,32 +172,32 @@ public class MediaTypeTest {
* unpleasant IllegalCharsetNameException.
*/
@Test public void testCharsetNameIsSingleQuoted() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;charset='utf-8'");
MediaType mediaType = parse("text/plain;charset='utf-8'");
assertEquals("UTF-8", mediaType.charset().name());
}
@Test public void testCharsetNameIsDoubleQuotedAndSingleQuoted() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;charset=\"'utf-8'\"");
MediaType mediaType = parse("text/plain;charset=\"'utf-8'\"");
assertNull(mediaType.charset());
}
@Test public void testCharsetNameIsDoubleQuotedSingleQuote() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;charset=\"'\"");
MediaType mediaType = parse("text/plain;charset=\"'\"");
assertNull(mediaType.charset());
}
@Test public void testDefaultCharset() throws Exception {
MediaType noCharset = MediaType.parse("text/plain");
MediaType noCharset = parse("text/plain");
assertEquals("UTF-8", noCharset.charset(Util.UTF_8).name());
assertEquals("US-ASCII", noCharset.charset(Charset.forName("US-ASCII")).name());
MediaType charset = MediaType.parse("text/plain; charset=iso-8859-1");
MediaType charset = parse("text/plain; charset=iso-8859-1");
assertEquals("ISO-8859-1", charset.charset(Util.UTF_8).name());
assertEquals("ISO-8859-1", charset.charset(Charset.forName("US-ASCII")).name());
}
@Test public void testParseDanglingSemicolon() throws Exception {
MediaType mediaType = MediaType.parse("text/plain;");
MediaType mediaType = parse("text/plain;");
assertEquals("text", mediaType.type());
assertEquals("plain", mediaType.subtype());
assertNull(mediaType.charset());
@ -171,11 +205,19 @@ public class MediaTypeTest {
}
private void assertMediaType(String string) {
MediaType mediaType = MediaType.parse(string);
assertEquals(string, mediaType.toString());
assertEquals(string, parse(string).toString());
}
private void assertInvalid(String string) {
assertNull(string, MediaType.parse(string));
private void assertInvalid(String string, String exceptionMessage) {
if (useGet) {
try {
parse(string);
fail("Expected get of \"" + string + "\" to throw with: " + exceptionMessage);
} catch (IllegalArgumentException e) {
assertEquals(exceptionMessage, e.getMessage());
}
} else {
assertNull(string, parse(string));
}
}
}

View File

@ -129,13 +129,13 @@ public final class MultipartBodyTest {
.addPart(
Headers.of("Content-Disposition", "file; filename=\"file1.txt\""),
RequestBody.create(
MediaType.parse("text/plain"), "... contents of file1.txt ..."))
MediaType.get("text/plain"), "... contents of file1.txt ..."))
.addPart(
Headers.of(
"Content-Disposition", "file; filename=\"file2.gif\"",
"Content-Transfer-Encoding", "binary"),
RequestBody.create(
MediaType.parse("image/gif"),
MediaType.get("image/gif"),
"... contents of file2.gif ...".getBytes(UTF_8)))
.build())
.build();
@ -180,7 +180,7 @@ public final class MultipartBodyTest {
MultipartBody body = new MultipartBody.Builder("AaB03x")
.setType(MultipartBody.FORM)
.addFormDataPart("field with spaces", "filename with spaces.txt",
RequestBody.create(MediaType.parse("text/plain; charset=utf-8"), "okay"))
RequestBody.create(MediaType.get("text/plain; charset=utf-8"), "okay"))
.addFormDataPart("field with \"", "\"")
.addFormDataPart("field with %22", "%22")
.addFormDataPart("field with \u0391", "Alpha")

View File

@ -31,7 +31,7 @@ import static org.junit.Assert.fail;
public final class RequestTest {
@Test public void string() throws Exception {
MediaType contentType = MediaType.parse("text/plain; charset=utf-8");
MediaType contentType = MediaType.get("text/plain; charset=utf-8");
RequestBody body = RequestBody.create(contentType, "abc".getBytes(Util.UTF_8));
assertEquals(contentType, body.contentType());
assertEquals(3, body.contentLength());
@ -40,15 +40,15 @@ public final class RequestTest {
}
@Test public void stringWithDefaultCharsetAdded() throws Exception {
MediaType contentType = MediaType.parse("text/plain");
MediaType contentType = MediaType.get("text/plain");
RequestBody body = RequestBody.create(contentType, "\u0800");
assertEquals(MediaType.parse("text/plain; charset=utf-8"), body.contentType());
assertEquals(MediaType.get("text/plain; charset=utf-8"), body.contentType());
assertEquals(3, body.contentLength());
assertEquals("e0a080", bodyToHex(body));
}
@Test public void stringWithNonDefaultCharsetSpecified() throws Exception {
MediaType contentType = MediaType.parse("text/plain; charset=utf-16be");
MediaType contentType = MediaType.get("text/plain; charset=utf-16be");
RequestBody body = RequestBody.create(contentType, "\u0800");
assertEquals(contentType, body.contentType());
assertEquals(2, body.contentLength());
@ -56,7 +56,7 @@ public final class RequestTest {
}
@Test public void byteArray() throws Exception {
MediaType contentType = MediaType.parse("text/plain");
MediaType contentType = MediaType.get("text/plain");
RequestBody body = RequestBody.create(contentType, "abc".getBytes(Util.UTF_8));
assertEquals(contentType, body.contentType());
assertEquals(3, body.contentLength());
@ -65,7 +65,7 @@ public final class RequestTest {
}
@Test public void byteArrayRange() throws Exception {
MediaType contentType = MediaType.parse("text/plain");
MediaType contentType = MediaType.get("text/plain");
RequestBody body = RequestBody.create(contentType, ".abcd".getBytes(Util.UTF_8), 1, 3);
assertEquals(contentType, body.contentType());
assertEquals(3, body.contentLength());
@ -79,7 +79,7 @@ public final class RequestTest {
writer.write("abc");
writer.close();
MediaType contentType = MediaType.parse("text/plain");
MediaType contentType = MediaType.get("text/plain");
RequestBody body = RequestBody.create(contentType, file);
assertEquals(contentType, body.contentType());
assertEquals(3, body.contentLength());
@ -89,7 +89,7 @@ public final class RequestTest {
/** Common verbs used for apis such as GitHub, AWS, and Google Cloud. */
@Test public void crudVerbs() throws IOException {
MediaType contentType = MediaType.parse("application/json");
MediaType contentType = MediaType.get("application/json");
RequestBody body = RequestBody.create(contentType, "{}");
Request get = new Request.Builder().url("http://localhost/api").get().build();

View File

@ -396,7 +396,7 @@ public final class ResponseBodyTest {
}
static ResponseBody body(String hex, String charset) {
MediaType mediaType = charset == null ? null : MediaType.parse("any/thing; charset=" + charset);
MediaType mediaType = charset == null ? null : MediaType.get("any/thing; charset=" + charset);
return ResponseBody.create(mediaType, ByteString.decodeHex(hex));
}

View File

@ -194,7 +194,7 @@ public final class HttpOverHttp2Test {
.url(server.url("/foo"))
.post(new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain; charset=utf-8");
return MediaType.get("text/plain; charset=utf-8");
}
@Override public void writeTo(BufferedSink sink) throws IOException {
@ -221,7 +221,7 @@ public final class HttpOverHttp2Test {
.url(server.url("/foo"))
.post(new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain; charset=utf-8");
return MediaType.get("text/plain; charset=utf-8");
}
@Override public long contentLength() throws IOException {
@ -252,7 +252,7 @@ public final class HttpOverHttp2Test {
.url(server.url("/foo"))
.post(new RequestBody() {
@Override public MediaType contentType() {
return MediaType.parse("text/plain; charset=utf-8");
return MediaType.get("text/plain; charset=utf-8");
}
@Override public long contentLength() throws IOException {

View File

@ -28,8 +28,7 @@ import static okhttp3.HttpUrl.FORM_ENCODE_SET;
import static okhttp3.HttpUrl.percentDecode;
public final class FormBody extends RequestBody {
private static final MediaType CONTENT_TYPE =
MediaType.parse("application/x-www-form-urlencoded");
private static final MediaType CONTENT_TYPE = MediaType.get("application/x-www-form-urlencoded");
private final List<String> encodedNames;
private final List<String> encodedValues;

View File

@ -45,12 +45,15 @@ public final class MediaType {
}
/**
* Returns a media type for {@code string}, or null if {@code string} is not a well-formed media
* type.
* Returns a media type for {@code string}.
*
* @throws IllegalArgumentException if {@code string} is not a well-formed media type.
*/
public static @Nullable MediaType parse(String string) {
public static MediaType get(String string) {
Matcher typeSubtype = TYPE_SUBTYPE.matcher(string);
if (!typeSubtype.lookingAt()) return null;
if (!typeSubtype.lookingAt()) {
throw new IllegalArgumentException("No subtype found for: \"" + string + '"');
}
String type = typeSubtype.group(1).toLowerCase(Locale.US);
String subtype = typeSubtype.group(2).toLowerCase(Locale.US);
@ -58,7 +61,13 @@ public final class MediaType {
Matcher parameter = PARAMETER.matcher(string);
for (int s = typeSubtype.end(); s < string.length(); s = parameter.end()) {
parameter.region(s, string.length());
if (!parameter.lookingAt()) return null; // This is not a well-formed media type.
if (!parameter.lookingAt()) {
throw new IllegalArgumentException("Parameter is not formatted correctly: \""
+ string.substring(s)
+ "\" for: \""
+ string
+ '"');
}
String name = parameter.group(1);
if (name == null || !name.equalsIgnoreCase("charset")) continue;
@ -74,7 +83,13 @@ public final class MediaType {
charsetParameter = parameter.group(3);
}
if (charset != null && !charsetParameter.equalsIgnoreCase(charset)) {
return null; // Multiple different charsets!
throw new IllegalArgumentException("Multiple charsets defined: \""
+ charset
+ "\" and: \""
+ charsetParameter
+ "\" for: \""
+ string
+ '"');
}
charset = charsetParameter;
}
@ -82,6 +97,18 @@ public final class MediaType {
return new MediaType(string, type, subtype, charset);
}
/**
* Returns a media type for {@code string}, or null if {@code string} is not a well-formed media
* type.
*/
public static @Nullable MediaType parse(String string) {
try {
return get(string);
} catch (IllegalArgumentException ignored) {
return null;
}
}
/**
* Returns the high-level media type, such as "text", "image", "audio", "video", or
* "application".

View File

@ -32,34 +32,34 @@ public final class MultipartBody extends RequestBody {
* need to be bundled in a particular order. Any "multipart" subtypes that an implementation does
* not recognize must be treated as being of subtype "mixed".
*/
public static final MediaType MIXED = MediaType.parse("multipart/mixed");
public static final MediaType MIXED = MediaType.get("multipart/mixed");
/**
* The "multipart/alternative" type is syntactically identical to "multipart/mixed", but the
* semantics are different. In particular, each of the body parts is an "alternative" version of
* the same information.
*/
public static final MediaType ALTERNATIVE = MediaType.parse("multipart/alternative");
public static final MediaType ALTERNATIVE = MediaType.get("multipart/alternative");
/**
* This type is syntactically identical to "multipart/mixed", but the semantics are different. In
* particular, in a digest, the default {@code Content-Type} value for a body part is changed from
* "text/plain" to "message/rfc822".
*/
public static final MediaType DIGEST = MediaType.parse("multipart/digest");
public static final MediaType DIGEST = MediaType.get("multipart/digest");
/**
* This type is syntactically identical to "multipart/mixed", but the semantics are different. In
* particular, in a parallel entity, the order of body parts is not significant.
*/
public static final MediaType PARALLEL = MediaType.parse("multipart/parallel");
public static final MediaType PARALLEL = MediaType.get("multipart/parallel");
/**
* The media-type multipart/form-data follows the rules of all multipart MIME data streams as
* outlined in RFC 2046. In forms, there are a series of fields to be supplied by the user who
* fills out the form. Each field has a name. Within a given form, the names are unique.
*/
public static final MediaType FORM = MediaType.parse("multipart/form-data");
public static final MediaType FORM = MediaType.get("multipart/form-data");
private static final byte[] COLONSPACE = {':', ' '};
private static final byte[] CRLF = {'\r', '\n'};
@ -74,7 +74,7 @@ public final class MultipartBody extends RequestBody {
MultipartBody(ByteString boundary, MediaType type, List<Part> parts) {
this.boundary = boundary;
this.originalType = type;
this.contentType = MediaType.parse(type + "; boundary=" + boundary.utf8());
this.contentType = MediaType.get(type + "; boundary=" + boundary.utf8());
this.parts = Util.immutableList(parts);
}

View File

@ -8,8 +8,7 @@ import okhttp3.RequestBody;
import okhttp3.Response;
public class PostExample {
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();

View File

@ -25,7 +25,7 @@ import okhttp3.Response;
public final class PostFile {
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
= MediaType.get("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();

View File

@ -30,7 +30,7 @@ public final class PostMultipart {
* these examples, please request your own client ID! https://api.imgur.com/oauth2
*/
private static final String IMGUR_CLIENT_ID = "9199fdef135c122";
private static final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
private static final MediaType MEDIA_TYPE_PNG = MediaType.get("image/png");
private final OkHttpClient client = new OkHttpClient();

View File

@ -25,7 +25,7 @@ import okio.BufferedSink;
public final class PostStreaming {
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
= MediaType.get("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();

View File

@ -27,7 +27,7 @@ import okio.Pipe;
public final class PostStreamingWithPipe {
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
= MediaType.get("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();

View File

@ -24,7 +24,7 @@ import okhttp3.Response;
public final class PostString {
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/x-markdown; charset=utf-8");
= MediaType.get("text/x-markdown; charset=utf-8");
private final OkHttpClient client = new OkHttpClient();

View File

@ -39,7 +39,7 @@ public final class RequestBodyCompression {
* https://console.developers.google.com/project
*/
public static final String GOOGLE_API_KEY = "AIzaSyAx2WZYe0My0i-uGurpvraYJxO7XNbwiGs";
public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json");
public static final MediaType MEDIA_TYPE_JSON = MediaType.get("application/json");
private final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new GzipRequestInterceptor())