Skip to content

Commit 7a139fc

Browse files
authored
Convert java.util.Date to java.time.Instant (jsr-310) (#58)
* Convert java.util.Date to java.time.Instant (jsr-310) * Fix typo and refacto parseHttpDate * Fix typo * Fix typo
1 parent 05435e7 commit 7a139fc

File tree

9 files changed

+130
-153
lines changed

9 files changed

+130
-153
lines changed

src/main/java/io/vertx/httpproxy/impl/CachingFilter.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import io.vertx.httpproxy.ProxyResponse;
1212
import io.vertx.httpproxy.spi.cache.Cache;
1313

14-
import java.util.Date;
14+
import java.time.Instant;
1515
import java.util.function.BiFunction;
1616

1717
class CachingFilter implements ProxyInterceptor {
@@ -136,8 +136,8 @@ private Future<ProxyResponse> tryHandleProxyRequestFromCache(ProxyContext contex
136136
//
137137
String ifModifiedSinceHeader = response.getHeader(HttpHeaders.IF_MODIFIED_SINCE);
138138
if ((response.method() == HttpMethod.GET || response.method() == HttpMethod.HEAD) && ifModifiedSinceHeader != null && resource.lastModified != null) {
139-
Date ifModifiedSince = ParseUtils.parseHeaderDate(ifModifiedSinceHeader);
140-
if (resource.lastModified.getTime() <= ifModifiedSince.getTime()) {
139+
Instant ifModifiedSince = ParseUtils.parseHeaderDate(ifModifiedSinceHeader);
140+
if (!ifModifiedSince.isAfter(resource.lastModified)) {
141141
response.response().setStatusCode(304).end();
142142
return Future.succeededFuture();
143143
}

src/main/java/io/vertx/httpproxy/impl/HttpUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import io.vertx.core.MultiMap;
1414
import io.vertx.core.http.HttpHeaders;
1515

16-
import java.util.Date;
16+
import java.time.Instant;
1717
import java.util.List;
1818

1919
class HttpUtils {
@@ -35,13 +35,13 @@ static Boolean isChunked(MultiMap headers) {
3535
}
3636
}
3737

38-
static Date dateHeader(MultiMap headers) {
38+
static Instant dateHeader(MultiMap headers) {
3939
String dateHeader = headers.get(HttpHeaders.DATE);
4040
if (dateHeader == null) {
4141
List<String> warningHeaders = headers.getAll("warning");
4242
if (warningHeaders.size() > 0) {
4343
for (String warningHeader : warningHeaders) {
44-
Date date = ParseUtils.parseWarningHeaderDate(warningHeader);
44+
Instant date = ParseUtils.parseWarningHeaderDate(warningHeader);
4545
if (date != null) {
4646
return date;
4747
}

src/main/java/io/vertx/httpproxy/impl/ParseUtils.java

Lines changed: 30 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,38 @@
1010
*/
1111
package io.vertx.httpproxy.impl;
1212

13-
import java.text.SimpleDateFormat;
14-
import java.time.DayOfWeek;
15-
import java.util.Date;
16-
import java.util.Locale;
17-
import java.util.TimeZone;
13+
import java.time.*;
14+
import java.time.format.DateTimeFormatter;
15+
import java.time.format.DateTimeFormatterBuilder;
16+
import java.util.*;
1817

1918
/**
2019
* @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
2120
*/
2221
public class ParseUtils {
2322

24-
public static Date parseHeaderDate(String value) {
23+
public static final DateTimeFormatter RFC_850_DATE_TIME = new DateTimeFormatterBuilder()
24+
.appendPattern("EEEE, dd-MMM-yy HH:mm:ss")
25+
.parseLenient()
26+
.appendLiteral(" GMT")
27+
.toFormatter(Locale.US)
28+
.withZone(ZoneId.of("UTC"));
29+
30+
public static final DateTimeFormatter ASC_TIME = new DateTimeFormatterBuilder()
31+
.appendPattern("EEE MMM d HH:mm:ss yyyy")
32+
.parseLenient()
33+
.toFormatter(Locale.US)
34+
.withZone(ZoneId.of("UTC"));
35+
36+
public static Instant parseHeaderDate(String value) {
2537
try {
2638
return parseHttpDate(value);
2739
} catch (Exception e) {
2840
return null;
2941
}
3042
}
3143

32-
public static Date parseWarningHeaderDate(String value) {
44+
public static Instant parseWarningHeaderDate(String value) {
3345
// warn-code
3446
int index = value.indexOf(' ');
3547
if (index > 0) {
@@ -43,110 +55,27 @@ public static Date parseWarningHeaderDate(String value) {
4355
int len = value.length();
4456
if (index + 2 < len && value.charAt(index + 1) == '"' && value.charAt(len - 1) == '"') {
4557
// Space for 2 double quotes
46-
String date = value.substring(index + 2, len - 1);
47-
try {
48-
return parseHttpDate(date);
49-
} catch (Exception ignore) {
50-
}
58+
return parseHeaderDate(value.substring(index + 2, len - 1));
5159
}
5260
}
5361
}
5462
}
5563
return null;
5664
}
5765

58-
private static SimpleDateFormat RFC_1123_DATE_TIME() {
59-
SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
60-
format.setTimeZone(TimeZone.getTimeZone("GMT"));
61-
return format;
66+
public static String formatHttpDate(Instant date) {
67+
return DateTimeFormatter.RFC_1123_DATE_TIME.format(OffsetDateTime.ofInstant(date, ZoneOffset.UTC));
6268
}
6369

64-
private static SimpleDateFormat RFC_850_DATE_TIME() {
65-
SimpleDateFormat format = new SimpleDateFormat("EEEEEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US);
66-
format.setTimeZone(TimeZone.getTimeZone("GMT"));
67-
return format;
68-
}
69-
70-
private static SimpleDateFormat ASC_TIME() {
71-
SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US);
72-
format.setTimeZone(TimeZone.getTimeZone("GMT"));
73-
return format;
74-
}
75-
76-
public static String formatHttpDate(Date date) {
77-
return RFC_1123_DATE_TIME().format(date);
78-
}
79-
80-
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
81-
public static Date parseHttpDate(String value) throws Exception {
82-
int sep = 0;
83-
while (true) {
84-
if (sep < value.length()) {
85-
char c = value.charAt(sep);
86-
if (c == ',') {
87-
String s = value.substring(0, sep);
88-
if (parseWkday(s) != null) {
89-
// rfc1123-date
90-
return RFC_1123_DATE_TIME().parse(value);
91-
} else if (parseWeekday(s) != null) {
92-
// rfc850-date
93-
return RFC_850_DATE_TIME().parse(value);
94-
}
95-
return null;
96-
} else if (c == ' ') {
97-
String s = value.substring(0, sep);
98-
if (parseWkday(s) != null) {
99-
// asctime-date
100-
return ASC_TIME().parse(value);
101-
}
102-
return null;
103-
}
104-
sep++;
105-
} else {
106-
return null;
107-
}
108-
}
109-
}
110-
111-
private static DayOfWeek parseWkday(String value) {
112-
switch (value) {
113-
case "Mon":
114-
return DayOfWeek.MONDAY;
115-
case "Tue":
116-
return DayOfWeek.TUESDAY;
117-
case "Wed":
118-
return DayOfWeek.WEDNESDAY;
119-
case "Thu":
120-
return DayOfWeek.THURSDAY;
121-
case "Fri":
122-
return DayOfWeek.FRIDAY;
123-
case "Sat":
124-
return DayOfWeek.SATURDAY;
125-
case "Sun":
126-
return DayOfWeek.SUNDAY;
127-
default:
128-
return null;
70+
// https://www.rfc-editor.org/rfc/rfc9110#http.date
71+
public static Instant parseHttpDate(String value) throws Exception {
72+
int pos = value.indexOf(',');
73+
if (pos == 3) { // e.g. Sun, 06 Nov 1994 08:49:37 GMT
74+
return DateTimeFormatter.RFC_1123_DATE_TIME.parse(value, Instant::from);
12975
}
130-
}
131-
132-
private static DayOfWeek parseWeekday(String value) {
133-
switch (value) {
134-
case "Monday":
135-
return DayOfWeek.MONDAY;
136-
case "Tuesday":
137-
return DayOfWeek.TUESDAY;
138-
case "Wednesday":
139-
return DayOfWeek.WEDNESDAY;
140-
case "Thursday":
141-
return DayOfWeek.THURSDAY;
142-
case "Friday":
143-
return DayOfWeek.FRIDAY;
144-
case "Saturday":
145-
return DayOfWeek.SATURDAY;
146-
case "Sunday":
147-
return DayOfWeek.SUNDAY;
148-
default:
149-
return null;
76+
if (pos == -1) { // e.g. Sun Nov 6 08:49:37 1994
77+
return ASC_TIME.parse(value, Instant::from);
15078
}
79+
return RFC_850_DATE_TIME.parse(value, Instant::from); // e.g. Sunday, 06-Nov-94 08:49:37 GMT
15180
}
15281
}

src/main/java/io/vertx/httpproxy/impl/ProxiedResponse.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
import io.vertx.httpproxy.ProxyRequest;
2727
import io.vertx.httpproxy.ProxyResponse;
2828

29+
import java.time.Instant;
2930
import java.util.ArrayList;
30-
import java.util.Date;
3131
import java.util.Iterator;
3232
import java.util.List;
3333

@@ -85,7 +85,7 @@ class ProxiedResponse implements ProxyResponse {
8585
String dateHeader = response.getHeader(HttpHeaders.DATE);
8686
String expiresHeader = response.getHeader(HttpHeaders.EXPIRES);
8787
if (dateHeader != null && expiresHeader != null) {
88-
maxAge = ParseUtils.parseHeaderDate(expiresHeader).getTime() - ParseUtils.parseHeaderDate(dateHeader).getTime();
88+
maxAge = ParseUtils.parseHeaderDate(expiresHeader).toEpochMilli() - ParseUtils.parseHeaderDate(dateHeader).toEpochMilli();
8989
}
9090
}
9191
}
@@ -176,9 +176,9 @@ public void send(Handler<AsyncResult<Void>> completionHandler) {
176176
}
177177

178178
// Date header
179-
Date date = HttpUtils.dateHeader(headers);
179+
Instant date = HttpUtils.dateHeader(headers);
180180
if (date == null) {
181-
date = new Date();
181+
date = Instant.now();
182182
}
183183
try {
184184
proxiedResponse.putHeader("date", ParseUtils.formatHttpDate(date));
@@ -191,12 +191,12 @@ public void send(Handler<AsyncResult<Void>> completionHandler) {
191191
if (warningHeaders.size() > 0) {
192192
warningHeaders = new ArrayList<>(warningHeaders);
193193
String dateHeader = headers.get("date");
194-
Date dateInstant = dateHeader != null ? ParseUtils.parseHeaderDate(dateHeader) : null;
194+
Instant dateInstant = dateHeader != null ? ParseUtils.parseHeaderDate(dateHeader) : null;
195195
Iterator<String> i = warningHeaders.iterator();
196196
// Suppress incorrect warning header
197197
while (i.hasNext()) {
198198
String warningHeader = i.next();
199-
Date warningInstant = ParseUtils.parseWarningHeaderDate(warningHeader);
199+
Instant warningInstant = ParseUtils.parseWarningHeaderDate(warningHeader);
200200
if (warningInstant != null && dateInstant != null && !warningInstant.equals(dateInstant)) {
201201
i.remove();
202202
}

src/main/java/io/vertx/httpproxy/impl/Resource.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@
1010
*/
1111
package io.vertx.httpproxy.impl;
1212

13-
import io.vertx.core.Future;
1413
import io.vertx.core.MultiMap;
1514
import io.vertx.core.buffer.Buffer;
1615
import io.vertx.core.http.HttpHeaders;
1716
import io.vertx.httpproxy.Body;
1817
import io.vertx.httpproxy.ProxyResponse;
1918

20-
import java.util.Date;
19+
import java.time.Instant;
2120

2221
class Resource {
2322

@@ -27,7 +26,7 @@ class Resource {
2726
final MultiMap headers;
2827
final long timestamp;
2928
final long maxAge;
30-
final Date lastModified;
29+
final Instant lastModified;
3130
final String etag;
3231
final Buffer content = Buffer.buffer();
3332

src/test/java/io/vertx/httpproxy/cache/CacheConditionalGetTest.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import org.junit.Rule;
2222
import org.junit.Test;
2323

24-
import java.util.Date;
24+
import java.time.Instant;
25+
import java.time.temporal.ChronoUnit;
2526
import java.util.concurrent.atomic.AtomicInteger;
2627

2728
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
@@ -58,9 +59,9 @@ public void testIfModifiedSinceRespondsNotModified(TestContext ctx) throws Excep
5859
.withStatus(200)
5960
.withHeader("Cache-Control", "public")
6061
.withHeader("ETag", "tag0")
61-
.withHeader("Date", ParseUtils.formatHttpDate(new Date(now)))
62-
.withHeader("Last-Modified", ParseUtils.formatHttpDate(new Date(now - 5000)))
63-
.withHeader("Expires", ParseUtils.formatHttpDate(new Date(now + 5000)))
62+
.withHeader("Date", ParseUtils.formatHttpDate(Instant.ofEpochMilli(now)))
63+
.withHeader("Last-Modified", ParseUtils.formatHttpDate(Instant.ofEpochMilli(now).minus(5000, ChronoUnit.MILLIS)))
64+
.withHeader("Expires", ParseUtils.formatHttpDate(Instant.ofEpochMilli(now).plus(5000, ChronoUnit.MILLIS)))
6465
.withBody("content")));
6566
startProxy(new SocketAddressImpl(8081, "localhost"));
6667
Async latch = ctx.async();
@@ -74,7 +75,7 @@ public void testIfModifiedSinceRespondsNotModified(TestContext ctx) throws Excep
7475
vertx.setTimer(3000, id -> {
7576
client.request(HttpMethod.GET, 8080, "localhost", "/img.jpg")
7677
.compose(req2 -> req2
77-
.putHeader(HttpHeaders.IF_MODIFIED_SINCE, ParseUtils.formatHttpDate(new Date(now - 5000)))
78+
.putHeader(HttpHeaders.IF_MODIFIED_SINCE, ParseUtils.formatHttpDate(Instant.ofEpochMilli(now).minus(5000, ChronoUnit.MILLIS)))
7879
.send()
7980
.compose(resp2 -> {
8081
ctx.assertEquals(304, resp2.statusCode());

0 commit comments

Comments
 (0)