diff --git a/okhttp/src/main/java/okhttp3/Cookie.kt b/okhttp/src/main/java/okhttp3/Cookie.kt index 9ab74d2f2..0a26109b4 100644 --- a/okhttp/src/main/java/okhttp3/Cookie.kt +++ b/okhttp/src/main/java/okhttp3/Cookie.kt @@ -18,7 +18,8 @@ package okhttp3 import okhttp3.internal.UTC import okhttp3.internal.canParseAsIpAddress import okhttp3.internal.delimiterOffset -import okhttp3.internal.http.HttpDate +import okhttp3.internal.http.MAX_DATE +import okhttp3.internal.http.toHttpDateString import okhttp3.internal.indexOfControlOrNonAscii import okhttp3.internal.publicsuffix.PublicSuffixDatabase import okhttp3.internal.toCanonicalHost @@ -217,7 +218,7 @@ class Cookie private constructor( if (expiresAt == Long.MIN_VALUE) { append("; max-age=0") } else { - append("; expires=").append(HttpDate.format(Date(expiresAt))) + append("; expires=").append(Date(expiresAt).toHttpDateString()) } } @@ -250,7 +251,7 @@ class Cookie private constructor( class Builder { private var name: String? = null private var value: String? = null - private var expiresAt = HttpDate.MAX_DATE + private var expiresAt = MAX_DATE private var domain: String? = null private var path = "/" private var secure = false @@ -271,7 +272,7 @@ class Cookie private constructor( fun expiresAt(expiresAt: Long) = apply { var expiresAt = expiresAt if (expiresAt <= 0L) expiresAt = Long.MIN_VALUE - if (expiresAt > HttpDate.MAX_DATE) expiresAt = HttpDate.MAX_DATE + if (expiresAt > MAX_DATE) expiresAt = MAX_DATE this.expiresAt = expiresAt this.persistent = true } @@ -374,7 +375,7 @@ class Cookie private constructor( val cookieValue = setCookie.trimSubstring(pairEqualsSign + 1, cookiePairEnd) if (cookieValue.indexOfControlOrNonAscii() != -1) return null - var expiresAt = HttpDate.MAX_DATE + var expiresAt = MAX_DATE var deltaSeconds = -1L var domain: String? = null var path: String? = null @@ -446,8 +447,8 @@ class Cookie private constructor( Long.MAX_VALUE } expiresAt = currentTimeMillis + deltaMilliseconds - if (expiresAt < currentTimeMillis || expiresAt > HttpDate.MAX_DATE) { - expiresAt = HttpDate.MAX_DATE // Handle overflow & limit the date range. + if (expiresAt < currentTimeMillis || expiresAt > MAX_DATE) { + expiresAt = MAX_DATE // Handle overflow & limit the date range. } } diff --git a/okhttp/src/main/java/okhttp3/Headers.kt b/okhttp/src/main/java/okhttp3/Headers.kt index 0fe5f2e90..127cb6459 100644 --- a/okhttp/src/main/java/okhttp3/Headers.kt +++ b/okhttp/src/main/java/okhttp3/Headers.kt @@ -19,7 +19,8 @@ package okhttp3 import okhttp3.Headers.Builder import okhttp3.internal.format -import okhttp3.internal.http.HttpDate +import okhttp3.internal.http.toHttpDateOrNull +import okhttp3.internal.http.toHttpDateString import org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement import java.time.Instant import java.util.ArrayList @@ -56,10 +57,7 @@ class Headers private constructor( * Returns the last value corresponding to the specified field parsed as an HTTP date, or null if * either the field is absent or cannot be parsed as a date. */ - fun getDate(name: String): Date? { - val value = get(name) - return if (value != null) HttpDate.parse(value) else null - } + fun getDate(name: String): Date? = get(name)?.toHttpDateOrNull() /** * Returns the last value corresponding to the specified field parsed as an HTTP date, or null if @@ -271,7 +269,7 @@ class Headers private constructor( * value. */ fun add(name: String, value: Date) = apply { - add(name, HttpDate.format(value)) + add(name, value.toHttpDateString()) } /** @@ -288,7 +286,7 @@ class Headers private constructor( * found, the existing values are replaced. */ operator fun set(name: String, value: Date) = apply { - set(name, HttpDate.format(value)) + set(name, value.toHttpDateString()) } /** diff --git a/okhttp/src/main/java/okhttp3/internal/cache/CacheStrategy.kt b/okhttp/src/main/java/okhttp3/internal/cache/CacheStrategy.kt index 5ad6f4e32..a1149bec0 100644 --- a/okhttp/src/main/java/okhttp3/internal/cache/CacheStrategy.kt +++ b/okhttp/src/main/java/okhttp3/internal/cache/CacheStrategy.kt @@ -17,8 +17,8 @@ package okhttp3.internal.cache import okhttp3.Request import okhttp3.Response -import okhttp3.internal.http.HttpDate import okhttp3.internal.http.StatusLine +import okhttp3.internal.http.toHttpDateOrNull import okhttp3.internal.toNonNegativeInt import java.net.HttpURLConnection.HTTP_BAD_METHOD import java.net.HttpURLConnection.HTTP_GONE @@ -104,14 +104,14 @@ class CacheStrategy internal constructor( val value = headers.value(i) when { fieldName.equals("Date", ignoreCase = true) -> { - servedDate = HttpDate.parse(value) + servedDate = value.toHttpDateOrNull() servedDateString = value } fieldName.equals("Expires", ignoreCase = true) -> { - expires = HttpDate.parse(value) + expires = value.toHttpDateOrNull() } fieldName.equals("Last-Modified", ignoreCase = true) -> { - lastModified = HttpDate.parse(value) + lastModified = value.toHttpDateOrNull() lastModifiedString = value } fieldName.equals("ETag", ignoreCase = true) -> { diff --git a/okhttp/src/main/java/okhttp3/internal/http/HttpDate.kt b/okhttp/src/main/java/okhttp3/internal/http/HttpDate.kt deleted file mode 100644 index f360e49b2..000000000 --- a/okhttp/src/main/java/okhttp3/internal/http/HttpDate.kt +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2011 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 okhttp3.internal.http - -import okhttp3.internal.UTC -import java.text.DateFormat -import java.text.ParsePosition -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale - -/** - * Best-effort parser for HTTP dates. - */ -object HttpDate { - /** The last four-digit year: "Fri, 31 Dec 9999 23:59:59 GMT". */ - const val MAX_DATE = 253402300799999L - - /** - * Most websites serve cookies in the blessed format. Eagerly create the parser to ensure such - * cookies are on the fast path. - */ - private val STANDARD_DATE_FORMAT = object : ThreadLocal() { - override fun initialValue(): DateFormat { - // Date format specified by RFC 7231 section 7.1.1.1. - return SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US).apply { - isLenient = false - timeZone = UTC - } - } - } - - /** If we fail to parse a date in a non-standard format, try each of these formats in sequence. */ - private val BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS = arrayOf( - // HTTP formats required by RFC2616 but with any timezone. - "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC 822, updated by RFC 1123 with any TZ - "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 850, obsoleted by RFC 1036 with any TZ. - "EEE MMM d HH:mm:ss yyyy", // ANSI C's asctime() format - // Alternative formats. - "EEE, dd-MMM-yyyy HH:mm:ss z", - "EEE, dd-MMM-yyyy HH-mm-ss z", - "EEE, dd MMM yy HH:mm:ss z", - "EEE dd-MMM-yyyy HH:mm:ss z", - "EEE dd MMM yyyy HH:mm:ss z", - "EEE dd-MMM-yyyy HH-mm-ss z", - "EEE dd-MMM-yy HH:mm:ss z", - "EEE dd MMM yy HH:mm:ss z", - "EEE,dd-MMM-yy HH:mm:ss z", - "EEE,dd-MMM-yyyy HH:mm:ss z", - "EEE, dd-MM-yyyy HH:mm:ss z", - - /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */ - "EEE MMM d yyyy HH:mm:ss z" - ) - - private val BROWSER_COMPATIBLE_DATE_FORMATS = arrayOfNulls(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.size) - - /** Returns the date for [value]. Returns null if the value couldn't be parsed. */ - fun parse(value: String): Date? { - if (value.isEmpty()) { - return null - } - - val position = ParsePosition(0) - var result = STANDARD_DATE_FORMAT.get().parse(value, position) - if (position.index == value.length) { - // STANDARD_DATE_FORMAT must match exactly; all text must be consumed, e.g. no ignored - // non-standard trailing "+01:00". Those cases are covered below. - return result - } - synchronized(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS) { - for (i in 0 until BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.size) { - var format: DateFormat? = BROWSER_COMPATIBLE_DATE_FORMATS[i] - if (format == null) { - format = SimpleDateFormat(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS[i], Locale.US).apply { - // Set the timezone to use when interpreting formats that don't have a timezone. GMT is - // specified by RFC 7231. - timeZone = UTC - } - BROWSER_COMPATIBLE_DATE_FORMATS[i] = format - } - position.index = 0 - result = format.parse(value, position) - if (position.index != 0) { - // Something was parsed. It's possible the entire string was not consumed but we ignore - // that. If any of the BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS ended in "'GMT'" we'd have - // to also check that position.getIndex() == value.length() otherwise parsing might have - // terminated early, ignoring things like "+01:00". Leaving this as != 0 means that any - // trailing junk is ignored. - return result - } - } - } - return null - } - - /** Returns the string for [value]. */ - fun format(value: Date): String { - return STANDARD_DATE_FORMAT.get().format(value) - } -} diff --git a/okhttp/src/main/java/okhttp3/internal/http/dates.kt b/okhttp/src/main/java/okhttp3/internal/http/dates.kt new file mode 100644 index 000000000..0b4675830 --- /dev/null +++ b/okhttp/src/main/java/okhttp3/internal/http/dates.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2011 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 okhttp3.internal.http + +import okhttp3.internal.UTC +import java.text.DateFormat +import java.text.ParsePosition +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +/** The last four-digit year: "Fri, 31 Dec 9999 23:59:59 GMT". */ +internal const val MAX_DATE = 253402300799999L + +/** + * Most websites serve cookies in the blessed format. Eagerly create the parser to ensure such + * cookies are on the fast path. + */ +private val STANDARD_DATE_FORMAT = object : ThreadLocal() { + override fun initialValue(): DateFormat { + // Date format specified by RFC 7231 section 7.1.1.1. + return SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US).apply { + isLenient = false + timeZone = UTC + } + } +} + +/** If we fail to parse a date in a non-standard format, try each of these formats in sequence. */ +private val BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS = arrayOf( + // HTTP formats required by RFC2616 but with any timezone. + "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC 822, updated by RFC 1123 with any TZ + "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 850, obsoleted by RFC 1036 with any TZ. + "EEE MMM d HH:mm:ss yyyy", // ANSI C's asctime() format + // Alternative formats. + "EEE, dd-MMM-yyyy HH:mm:ss z", + "EEE, dd-MMM-yyyy HH-mm-ss z", + "EEE, dd MMM yy HH:mm:ss z", + "EEE dd-MMM-yyyy HH:mm:ss z", + "EEE dd MMM yyyy HH:mm:ss z", + "EEE dd-MMM-yyyy HH-mm-ss z", + "EEE dd-MMM-yy HH:mm:ss z", + "EEE dd MMM yy HH:mm:ss z", + "EEE,dd-MMM-yy HH:mm:ss z", + "EEE,dd-MMM-yyyy HH:mm:ss z", + "EEE, dd-MM-yyyy HH:mm:ss z", + + /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */ + "EEE MMM d yyyy HH:mm:ss z" +) + +private val BROWSER_COMPATIBLE_DATE_FORMATS = + arrayOfNulls(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.size) + +/** Returns the date for this string, or null if the value couldn't be parsed. */ +internal fun String.toHttpDateOrNull(): Date? { + if (isEmpty()) return null + + val position = ParsePosition(0) + var result = STANDARD_DATE_FORMAT.get().parse(this, position) + if (position.index == length) { + // STANDARD_DATE_FORMAT must match exactly; all text must be consumed, e.g. no ignored + // non-standard trailing "+01:00". Those cases are covered below. + return result + } + synchronized(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS) { + for (i in 0 until BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.size) { + var format: DateFormat? = BROWSER_COMPATIBLE_DATE_FORMATS[i] + if (format == null) { + format = SimpleDateFormat(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS[i], Locale.US).apply { + // Set the timezone to use when interpreting formats that don't have a timezone. GMT is + // specified by RFC 7231. + timeZone = UTC + } + BROWSER_COMPATIBLE_DATE_FORMATS[i] = format + } + position.index = 0 + result = format.parse(this, position) + if (position.index != 0) { + // Something was parsed. It's possible the entire string was not consumed but we ignore + // that. If any of the BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS ended in "'GMT'" we'd have + // to also check that position.getIndex() == value.length() otherwise parsing might have + // terminated early, ignoring things like "+01:00". Leaving this as != 0 means that any + // trailing junk is ignored. + return result + } + } + } + return null +} + +/** Returns the string for this date. */ +internal fun Date.toHttpDateString(): String = STANDARD_DATE_FORMAT.get().format(this) diff --git a/okhttp/src/test/java/okhttp3/CookieTest.java b/okhttp/src/test/java/okhttp3/CookieTest.java index 230fae6fa..bf2add65e 100644 --- a/okhttp/src/test/java/okhttp3/CookieTest.java +++ b/okhttp/src/test/java/okhttp3/CookieTest.java @@ -21,11 +21,11 @@ import java.util.Date; import java.util.List; import java.util.Objects; import okhttp3.internal.Util; -import okhttp3.internal.http.HttpDate; import org.junit.Test; import static java.util.Arrays.asList; import static okhttp3.internal.Internal.parseCookie; +import static okhttp3.internal.http.DatesKt.MAX_DATE; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; @@ -93,32 +93,35 @@ public final class CookieTest { } @Test public void maxAge() throws Exception { - assertThat(parseCookie(50000L, url, "a=b; Max-Age=1").expiresAt()).isEqualTo(51000L); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=9223372036854724").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=9223372036854725").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=9223372036854726").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(parseCookie(9223372036854773807L, url, "a=b; Max-Age=1").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(parseCookie(9223372036854773807L, url, "a=b; Max-Age=2").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(parseCookie(9223372036854773807L, url, "a=b; Max-Age=3").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=10000000000000000000").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=1").expiresAt()) + .isEqualTo(51000L); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=9223372036854724").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=9223372036854725").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=9223372036854726").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(parseCookie(9223372036854773807L, url, "a=b; Max-Age=1").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(parseCookie(9223372036854773807L, url, "a=b; Max-Age=2").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(parseCookie(9223372036854773807L, url, "a=b; Max-Age=3").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=10000000000000000000").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void maxAgeNonPositive() throws Exception { - assertThat(parseCookie(50000L, url, "a=b; Max-Age=-1").expiresAt()).isEqualTo(Long.MIN_VALUE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=0").expiresAt()).isEqualTo(Long.MIN_VALUE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=-9223372036854775808").expiresAt()).isEqualTo( - Long.MIN_VALUE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=-9223372036854775809").expiresAt()).isEqualTo( - Long.MIN_VALUE); - assertThat(parseCookie(50000L, url, "a=b; Max-Age=-10000000000000000000").expiresAt()).isEqualTo( - Long.MIN_VALUE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=-1").expiresAt()) + .isEqualTo(Long.MIN_VALUE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=0").expiresAt()) + .isEqualTo(Long.MIN_VALUE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=-9223372036854775808").expiresAt()) + .isEqualTo(Long.MIN_VALUE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=-9223372036854775809").expiresAt()) + .isEqualTo(Long.MIN_VALUE); + assertThat(parseCookie(50000L, url, "a=b; Max-Age=-10000000000000000000").expiresAt()) + .isEqualTo(Long.MIN_VALUE); } @Test public void domainAndPath() throws Exception { @@ -139,76 +142,75 @@ public final class CookieTest { } @Test public void expiresDate() throws Exception { - assertThat(new Date( - Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:00:00 GMT").expiresAt())).isEqualTo( - date("1970-01-01T00:00:00.000+0000")); - assertThat(new Date( - Cookie.parse(url, "a=b; Expires=Wed, 09 Jun 2021 10:18:14 GMT").expiresAt())).isEqualTo( - date("2021-06-09T10:18:14.000+0000")); - assertThat(new Date( - Cookie.parse(url, "a=b; Expires=Sun, 06 Nov 1994 08:49:37 GMT").expiresAt())).isEqualTo( - date("1994-11-06T08:49:37.000+0000")); + assertThat(new Date(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:00:00 GMT") + .expiresAt())).isEqualTo(date("1970-01-01T00:00:00.000+0000")); + assertThat(new Date(Cookie.parse(url, "a=b; Expires=Wed, 09 Jun 2021 10:18:14 GMT") + .expiresAt())).isEqualTo(date("2021-06-09T10:18:14.000+0000")); + assertThat(new Date(Cookie.parse(url, "a=b; Expires=Sun, 06 Nov 1994 08:49:37 GMT") + .expiresAt())).isEqualTo(date("1994-11-06T08:49:37.000+0000")); } @Test public void awkwardDates() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 70 00:00:00 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 January 1970 00:00:00 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Janucember 1970 00:00:00 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 1 Jan 1970 00:00:00 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 0:00:00 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:0:00 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:00:0 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=00:00:00 Thu, 01 Jan 1970 GMT").expiresAt()).isEqualTo( - 0L); - assertThat(Cookie.parse(url, "a=b; Expires=00:00:00 1970 Jan 01").expiresAt()).isEqualTo(0L); - assertThat(Cookie.parse(url, "a=b; Expires=00:00:00 1970 Jan 1").expiresAt()).isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 70 00:00:00 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 January 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Janucember 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 1 Jan 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 0:00:00 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:0:00 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:00:0 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=00:00:00 Thu, 01 Jan 1970 GMT").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=00:00:00 1970 Jan 01").expiresAt()) + .isEqualTo(0L); + assertThat(Cookie.parse(url, "a=b; Expires=00:00:00 1970 Jan 1").expiresAt()) + .isEqualTo(0L); } @Test public void invalidYear() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1600 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 19999 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1600 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 19999 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void invalidMonth() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Foo 1970 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Foocember 1970 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 1970 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Foo 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Foocember 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void invalidDayOfMonth() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 32 Jan 1970 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); - assertThat(Cookie.parse(url, "a=b; Expires=Thu, Jan 1970 00:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 32 Jan 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, Jan 1970 00:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void invalidHour() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 24:00:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 24:00:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void invalidMinute() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:60:00 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:60:00 GMT").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void invalidSecond() throws Exception { - assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:00:60 GMT").expiresAt()).isEqualTo( - HttpDate.MAX_DATE); + assertThat(Cookie.parse(url, "a=b; Expires=Thu, 01 Jan 1970 00:00:60 GMT").expiresAt()) + .isEqualTo(MAX_DATE); } @Test public void domainMatches() throws Exception { @@ -389,7 +391,8 @@ public final class CookieTest { @Test public void maxAgeOrExpiresMakesCookiePersistent() throws Exception { assertThat(parseCookie(0L, url, "a=b").persistent()).isFalse(); assertThat(parseCookie(0L, url, "a=b; Max-Age=1").persistent()).isTrue(); - assertThat(parseCookie(0L, url, "a=b; Expires=Thu, 01 Jan 1970 00:00:01 GMT").persistent()).isTrue(); + assertThat(parseCookie(0L, url, "a=b; Expires=Thu, 01 Jan 1970 00:00:01 GMT").persistent()) + .isTrue(); } @Test public void parseAll() throws Exception { @@ -411,7 +414,7 @@ public final class CookieTest { .build(); assertThat(cookie.name()).isEqualTo("a"); assertThat(cookie.value()).isEqualTo("b"); - assertThat(cookie.expiresAt()).isEqualTo(HttpDate.MAX_DATE); + assertThat(cookie.expiresAt()).isEqualTo(MAX_DATE); assertThat(cookie.domain()).isEqualTo("example.com"); assertThat(cookie.path()).isEqualTo("/"); assertThat(cookie.secure()).isFalse(); diff --git a/okhttp/src/test/java/okhttp3/internal/http/HttpDateTest.kt b/okhttp/src/test/java/okhttp3/internal/http/HttpDateTest.kt index 0abf206af..a1c5dbd54 100644 --- a/okhttp/src/test/java/okhttp3/internal/http/HttpDateTest.kt +++ b/okhttp/src/test/java/okhttp3/internal/http/HttpDateTest.kt @@ -44,53 +44,53 @@ class HttpDateTest { @Test @Throws(Exception::class) fun parseStandardFormats() { // RFC 822, updated by RFC 1123 with GMT. - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00:00 GMT")!!.time).isEqualTo(0L) - assertThat(HttpDate.parse("Fri, 06 Jun 2014 12:30:30 GMT")!!.time).isEqualTo(1402057830000L) + assertThat("Thu, 01 Jan 1970 00:00:00 GMT".toHttpDateOrNull()!!.time).isEqualTo(0L) + assertThat("Fri, 06 Jun 2014 12:30:30 GMT".toHttpDateOrNull()!!.time).isEqualTo(1402057830000L) // RFC 850, obsoleted by RFC 1036 with GMT. - assertThat(HttpDate.parse("Thursday, 01-Jan-70 00:00:00 GMT")!!.time).isEqualTo(0L) - assertThat(HttpDate.parse("Friday, 06-Jun-14 12:30:30 GMT")!!.time).isEqualTo(1402057830000L) + assertThat("Thursday, 01-Jan-70 00:00:00 GMT".toHttpDateOrNull()!!.time).isEqualTo(0L) + assertThat("Friday, 06-Jun-14 12:30:30 GMT".toHttpDateOrNull()!!.time).isEqualTo(1402057830000L) // ANSI C's asctime(): should use GMT, not platform default. - assertThat(HttpDate.parse("Thu Jan 1 00:00:00 1970")!!.time).isEqualTo(0L) - assertThat(HttpDate.parse("Fri Jun 6 12:30:30 2014")!!.time).isEqualTo(1402057830000L) + assertThat("Thu Jan 1 00:00:00 1970".toHttpDateOrNull()!!.time).isEqualTo(0L) + assertThat("Fri Jun 6 12:30:30 2014".toHttpDateOrNull()!!.time).isEqualTo(1402057830000L) } @Test @Throws(Exception::class) fun format() { - assertThat(HttpDate.format(Date(0L))).isEqualTo("Thu, 01 Jan 1970 00:00:00 GMT") - assertThat(HttpDate.format(Date(1402057830000L))).isEqualTo("Fri, 06 Jun 2014 12:30:30 GMT") + assertThat(Date(0L).toHttpDateString()).isEqualTo("Thu, 01 Jan 1970 00:00:00 GMT") + assertThat(Date(1402057830000L).toHttpDateString()).isEqualTo("Fri, 06 Jun 2014 12:30:30 GMT") } @Test @Throws(Exception::class) fun parseNonStandardStrings() { // RFC 822, updated by RFC 1123 with any TZ - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00:00 GMT-01:00")!!.time).isEqualTo(3600000L) - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00:00 PST")!!.time).isEqualTo(28800000L) + assertThat("Thu, 01 Jan 1970 00:00:00 GMT-01:00".toHttpDateOrNull()!!.time).isEqualTo(3600000L) + assertThat("Thu, 01 Jan 1970 00:00:00 PST".toHttpDateOrNull()!!.time).isEqualTo(28800000L) // Ignore trailing junk - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00:00 GMT JUNK")!!.time).isEqualTo(0L) + assertThat("Thu, 01 Jan 1970 00:00:00 GMT JUNK".toHttpDateOrNull()!!.time).isEqualTo(0L) // Missing timezones treated as bad. - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00:00")).isNull() + assertThat("Thu, 01 Jan 1970 00:00:00".toHttpDateOrNull()).isNull() // Missing seconds treated as bad. - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00 GMT")).isNull() + assertThat("Thu, 01 Jan 1970 00:00 GMT".toHttpDateOrNull()).isNull() // Extra spaces treated as bad. - assertThat(HttpDate.parse("Thu, 01 Jan 1970 00:00 GMT")).isNull() + assertThat("Thu, 01 Jan 1970 00:00 GMT".toHttpDateOrNull()).isNull() // Missing leading zero treated as bad. - assertThat(HttpDate.parse("Thu, 1 Jan 1970 00:00 GMT")).isNull() + assertThat("Thu, 1 Jan 1970 00:00 GMT".toHttpDateOrNull()).isNull() // RFC 850, obsoleted by RFC 1036 with any TZ. - assertThat(HttpDate.parse("Thursday, 01-Jan-1970 00:00:00 GMT-01:00")!!.time) + assertThat("Thursday, 01-Jan-1970 00:00:00 GMT-01:00".toHttpDateOrNull()!!.time) .isEqualTo(3600000L) - assertThat(HttpDate.parse("Thursday, 01-Jan-1970 00:00:00 PST")!!.time) + assertThat("Thursday, 01-Jan-1970 00:00:00 PST".toHttpDateOrNull()!!.time) .isEqualTo(28800000L) // Ignore trailing junk - assertThat(HttpDate.parse("Thursday, 01-Jan-1970 00:00:00 PST JUNK")!!.time) + assertThat("Thursday, 01-Jan-1970 00:00:00 PST JUNK".toHttpDateOrNull()!!.time) .isEqualTo(28800000L) // ANSI C's asctime() format // This format ignores the timezone entirely even if it is present and uses GMT. - assertThat(HttpDate.parse("Fri Jun 6 12:30:30 2014 PST")!!.time).isEqualTo(1402057830000L) + assertThat("Fri Jun 6 12:30:30 2014 PST".toHttpDateOrNull()!!.time).isEqualTo(1402057830000L) // Ignore trailing junk. - assertThat(HttpDate.parse("Fri Jun 6 12:30:30 2014 JUNK")!!.time).isEqualTo(1402057830000L) + assertThat("Fri Jun 6 12:30:30 2014 JUNK".toHttpDateOrNull()!!.time).isEqualTo(1402057830000L) } }