Fix date format in headers to use 2-digit day of month (#10259)
Motivation: `Date`, `Expires`, and `Set-Cookie` headers are being generated with a 1-digit day of month, e.g. `Sun, 6 Nov 1994 08:49:37 GMT`. RFC 2616 specifies that `Date` and `Expires` headers should use "a fixed-length subset of that defined by RFC 1123" which includes a 2-digit day of month. RFC6265 is lax in it's specification of the `Set-Cookie` header and permits a 2-digit day of month. See: https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html See: https://tools.ietf.org/html/rfc1123#page-55 See: https://tools.ietf.org/html/rfc6265#section-5.1.1 Modifications: - Update `DateFormatter` to correctly implement RFC 2616 headers Result: ``` Date: Sun, 06 Nov 1994 08:49:37 GMT Expires: Sun, 06 Nov 1994 08:49:37 GMT Set-Cookie: id=a3fWa; Expires=Sun, 06 Nov 1994 08:49:37 GMT ```
This commit is contained in:
parent
09d38c87df
commit
322d96ef92
@ -38,10 +38,12 @@ import java.util.TimeZone;
|
|||||||
* If you're looking for a date format that validates day of week, or supports other timezones, consider using
|
* If you're looking for a date format that validates day of week, or supports other timezones, consider using
|
||||||
* java.util.DateTimeFormatter.RFC_1123_DATE_TIME.
|
* java.util.DateTimeFormatter.RFC_1123_DATE_TIME.
|
||||||
*
|
*
|
||||||
* On the formatting side, it uses RFC1123 format.
|
* On the formatting side, it uses a subset of RFC1123 (2 digit day-of-month and 4 digit year) as per RFC2616.
|
||||||
|
* This subset supports RFC6265.
|
||||||
*
|
*
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc6265#section-5.1.1">RFC6265</a> for the parsing side
|
* @see <a href="https://tools.ietf.org/html/rfc6265#section-5.1.1">RFC6265</a> for the parsing side
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc1123#page-55">RFC1123</a> for the encoding side.
|
* @see <a href="https://tools.ietf.org/html/rfc1123#page-55">RFC1123</a> and
|
||||||
|
* <a href="https://tools.ietf.org/html/rfc2616#section-3.3.1">RFC2616</a> for the encoding side.
|
||||||
*/
|
*/
|
||||||
public final class DateFormatter {
|
public final class DateFormatter {
|
||||||
|
|
||||||
@ -429,7 +431,7 @@ public final class DateFormatter {
|
|||||||
cal.setTime(date);
|
cal.setTime(date);
|
||||||
|
|
||||||
sb.append(DAY_OF_WEEK_TO_SHORT_NAME[cal.get(Calendar.DAY_OF_WEEK) - 1]).append(", ");
|
sb.append(DAY_OF_WEEK_TO_SHORT_NAME[cal.get(Calendar.DAY_OF_WEEK) - 1]).append(", ");
|
||||||
sb.append(cal.get(Calendar.DAY_OF_MONTH)).append(' ');
|
appendZeroLeftPadded(cal.get(Calendar.DAY_OF_MONTH), sb).append(' ');
|
||||||
sb.append(CALENDAR_MONTH_TO_SHORT_NAME[cal.get(Calendar.MONTH)]).append(' ');
|
sb.append(CALENDAR_MONTH_TO_SHORT_NAME[cal.get(Calendar.MONTH)]).append(' ');
|
||||||
sb.append(cal.get(Calendar.YEAR)).append(' ');
|
sb.append(cal.get(Calendar.YEAR)).append(' ');
|
||||||
appendZeroLeftPadded(cal.get(Calendar.HOUR_OF_DAY), sb).append(':');
|
appendZeroLeftPadded(cal.get(Calendar.HOUR_OF_DAY), sb).append(':');
|
||||||
|
@ -43,90 +43,97 @@ public class DateFormatterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseWithDashSeparatorSingleDigitDay() {
|
public void testParseWithDashSeparatorSingleDigitDay() {
|
||||||
assertEquals(DATE, parseHttpDate("Sunday, 06-Nov-94 08:49:37 GMT"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseWithSingleDoubleDigitDay() {
|
|
||||||
assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 08:49:37 GMT"));
|
assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 08:49:37 GMT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParseWithDashSeparatorDoubleDigitDay() {
|
||||||
|
assertEquals(DATE, parseHttpDate("Sunday, 06-Nov-94 08:49:37 GMT"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseWithoutGMT() {
|
public void testParseWithoutGMT() {
|
||||||
assertEquals(DATE, parseHttpDate("Sun Nov 6 08:49:37 1994"));
|
assertEquals(DATE, parseHttpDate("Sun Nov 06 08:49:37 1994"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseWithFunkyTimezone() {
|
public void testParseWithFunkyTimezone() {
|
||||||
assertEquals(DATE, parseHttpDate("Sun Nov 6 08:49:37 1994 -0000"));
|
assertEquals(DATE, parseHttpDate("Sun Nov 06 08:49:37 1994 -0000"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseWithSingleDigitHourMinutesAndSecond() {
|
public void testParseWithSingleDigitHourMinutesAndSecond() {
|
||||||
assertEquals(DATE, parseHttpDate("Sunday, 6-Nov-94 8:49:37 GMT"));
|
assertEquals(DATE, parseHttpDate("Sunday, 06-Nov-94 8:49:37 GMT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseWithSingleDigitTime() {
|
public void testParseWithSingleDigitTime() {
|
||||||
assertEquals(DATE, parseHttpDate("Sunday, 6 Nov 1994 8:49:37 GMT"));
|
assertEquals(DATE, parseHttpDate("Sunday, 06 Nov 1994 8:49:37 GMT"));
|
||||||
|
|
||||||
Date _08_09_37 = new Date(TIMESTAMP - 40 * 60 * 1000);
|
Date _08_09_37 = new Date(TIMESTAMP - 40 * 60 * 1000);
|
||||||
assertEquals(_08_09_37, parseHttpDate("Sunday, 6 Nov 1994 8:9:37 GMT"));
|
assertEquals(_08_09_37, parseHttpDate("Sunday, 06 Nov 1994 8:9:37 GMT"));
|
||||||
assertEquals(_08_09_37, parseHttpDate("Sunday, 6 Nov 1994 8:09:37 GMT"));
|
assertEquals(_08_09_37, parseHttpDate("Sunday, 06 Nov 1994 8:09:37 GMT"));
|
||||||
|
|
||||||
Date _08_09_07 = new Date(TIMESTAMP - (40 * 60 + 30) * 1000);
|
Date _08_09_07 = new Date(TIMESTAMP - (40 * 60 + 30) * 1000);
|
||||||
assertEquals(_08_09_07, parseHttpDate("Sunday, 6 Nov 1994 8:9:7 GMT"));
|
assertEquals(_08_09_07, parseHttpDate("Sunday, 06 Nov 1994 8:9:7 GMT"));
|
||||||
assertEquals(_08_09_07, parseHttpDate("Sunday, 6 Nov 1994 8:9:07 GMT"));
|
assertEquals(_08_09_07, parseHttpDate("Sunday, 06 Nov 1994 8:9:07 GMT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseMidnight() {
|
public void testParseMidnight() {
|
||||||
assertEquals(new Date(784080000000L), parseHttpDate("Sunday, 6 Nov 1994 00:00:00 GMT"));
|
assertEquals(new Date(784080000000L), parseHttpDate("Sunday, 06 Nov 1994 00:00:00 GMT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseInvalidInput() {
|
public void testParseInvalidInput() {
|
||||||
// missing field
|
// missing field
|
||||||
assertNull(parseHttpDate("Sun, Nov 1994 08:49:37 GMT"));
|
assertNull(parseHttpDate("Sun, Nov 1994 08:49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 1994 08:49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 1994 08:49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 08:49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 08:49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 :49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 :49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 08::37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 08::37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 08:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49: GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 08:49: GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 08:49 GMT"));
|
||||||
//invalid value
|
//invalid value
|
||||||
assertNull(parseHttpDate("Sun, 6 FOO 1994 08:49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 FOO 1994 08:49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 36 Nov 1994 08:49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 36 Nov 1994 08:49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 28:49:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 28:49:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:69:37 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 08:69:37 GMT"));
|
||||||
assertNull(parseHttpDate("Sun, 6 Nov 1994 08:49:67 GMT"));
|
assertNull(parseHttpDate("Sun, 06 Nov 1994 08:49:67 GMT"));
|
||||||
//wrong number of digits in timestamp
|
//wrong number of digits in timestamp
|
||||||
assertNull(parseHttpDate("Sunday, 6 Nov 1994 0:0:000 GMT"));
|
assertNull(parseHttpDate("Sunday, 06 Nov 1994 0:0:000 GMT"));
|
||||||
assertNull(parseHttpDate("Sunday, 6 Nov 1994 0:000:0 GMT"));
|
assertNull(parseHttpDate("Sunday, 06 Nov 1994 0:000:0 GMT"));
|
||||||
assertNull(parseHttpDate("Sunday, 6 Nov 1994 000:0:0 GMT"));
|
assertNull(parseHttpDate("Sunday, 06 Nov 1994 000:0:0 GMT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFormat() {
|
public void testFormat() {
|
||||||
assertEquals("Sun, 6 Nov 1994 08:49:37 GMT", format(DATE));
|
assertEquals("Sun, 06 Nov 1994 08:49:37 GMT", format(DATE));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAppend() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
append(DATE, sb);
|
||||||
|
assertEquals("Sun, 06 Nov 1994 08:49:37 GMT", sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseAllMonths() {
|
public void testParseAllMonths() {
|
||||||
assertEquals(Calendar.JANUARY, getMonth(parseHttpDate("Sun, 6 Jan 1994 08:49:37 GMT")));
|
assertEquals(Calendar.JANUARY, getMonth(parseHttpDate("Sun, 06 Jan 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.FEBRUARY, getMonth(parseHttpDate("Sun, 6 Feb 1994 08:49:37 GMT")));
|
assertEquals(Calendar.FEBRUARY, getMonth(parseHttpDate("Sun, 06 Feb 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.MARCH, getMonth(parseHttpDate("Sun, 6 Mar 1994 08:49:37 GMT")));
|
assertEquals(Calendar.MARCH, getMonth(parseHttpDate("Sun, 06 Mar 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.APRIL, getMonth(parseHttpDate("Sun, 6 Apr 1994 08:49:37 GMT")));
|
assertEquals(Calendar.APRIL, getMonth(parseHttpDate("Sun, 06 Apr 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.MAY, getMonth(parseHttpDate("Sun, 6 May 1994 08:49:37 GMT")));
|
assertEquals(Calendar.MAY, getMonth(parseHttpDate("Sun, 06 May 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.JUNE, getMonth(parseHttpDate("Sun, 6 Jun 1994 08:49:37 GMT")));
|
assertEquals(Calendar.JUNE, getMonth(parseHttpDate("Sun, 06 Jun 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.JULY, getMonth(parseHttpDate("Sun, 6 Jul 1994 08:49:37 GMT")));
|
assertEquals(Calendar.JULY, getMonth(parseHttpDate("Sun, 06 Jul 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.AUGUST, getMonth(parseHttpDate("Sun, 6 Aug 1994 08:49:37 GMT")));
|
assertEquals(Calendar.AUGUST, getMonth(parseHttpDate("Sun, 06 Aug 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.SEPTEMBER, getMonth(parseHttpDate("Sun, 6 Sep 1994 08:49:37 GMT")));
|
assertEquals(Calendar.SEPTEMBER, getMonth(parseHttpDate("Sun, 06 Sep 1994 08:49:37 GMT")));
|
||||||
assertEquals(Calendar.OCTOBER, getMonth(parseHttpDate("Sun Oct 6 08:49:37 1994")));
|
assertEquals(Calendar.OCTOBER, getMonth(parseHttpDate("Sun Oct 06 08:49:37 1994")));
|
||||||
assertEquals(Calendar.NOVEMBER, getMonth(parseHttpDate("Sun Nov 6 08:49:37 1994")));
|
assertEquals(Calendar.NOVEMBER, getMonth(parseHttpDate("Sun Nov 06 08:49:37 1994")));
|
||||||
assertEquals(Calendar.DECEMBER, getMonth(parseHttpDate("Sun Dec 6 08:49:37 1994")));
|
assertEquals(Calendar.DECEMBER, getMonth(parseHttpDate("Sun Dec 06 08:49:37 1994")));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getMonth(Date referenceDate) {
|
private static int getMonth(Date referenceDate) {
|
||||||
|
Loading…
Reference in New Issue
Block a user