下面列出了怎么用 io.netty.handler.codec.DateFormatter 的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void testEncodingSingleCookieV0() throws ParseException {
int maxAge = 50;
String result =
"myCookie=myValue; Max-Age=50; Expires=(.+?); Path=/apathsomewhere; Domain=.adomainsomewhere; Secure";
Cookie cookie = new DefaultCookie("myCookie", "myValue");
cookie.setDomain(".adomainsomewhere");
cookie.setMaxAge(maxAge);
cookie.setPath("/apathsomewhere");
cookie.setSecure(true);
String encodedCookie = ServerCookieEncoder.STRICT.encode(cookie);
Matcher matcher = Pattern.compile(result).matcher(encodedCookie);
assertTrue(matcher.find());
Date expiresDate = DateFormatter.parseHttpDate(matcher.group(1));
long diff = (expiresDate.getTime() - System.currentTimeMillis()) / 1000;
// 2 secs should be fine
assertTrue(Math.abs(diff - maxAge) <= 2);
}
@Test
public void testDecodingSingleCookieV0() {
String cookieString = "myCookie=myValue;expires="
+ DateFormatter.format(new Date(System.currentTimeMillis() + 50000))
+ ";path=/apathsomewhere;domain=.adomainsomewhere;secure;";
Cookie cookie = ClientCookieDecoder.STRICT.decode(cookieString);
assertNotNull(cookie);
assertEquals("myValue", cookie.value());
assertEquals(".adomainsomewhere", cookie.domain());
assertNotEquals("maxAge should be defined when parsing cookie " + cookieString,
Long.MIN_VALUE, cookie.maxAge());
assertTrue("maxAge should be about 50ms when parsing cookie " + cookieString,
cookie.maxAge() >= 40 && cookie.maxAge() <= 60);
assertEquals("/apathsomewhere", cookie.path());
assertTrue(cookie.isSecure());
}
@Nullable
private static Long toTimeMillis(@Nullable String v) {
if (v == null) {
return null;
}
try {
@SuppressWarnings("UseOfObsoleteDateTimeApi")
final Date date = DateFormatter.parseHttpDate(v);
return date != null ? date.getTime() : null;
} catch (Exception ignore) {
// `parseHttpDate()` can raise an exception rather than returning `null`
// when the given value has more than 64 characters.
return null;
}
}
@Override
public long convertToTimeMillis(String value) {
@SuppressWarnings("UseOfObsoleteDateTimeApi")
Date date = null;
try {
date = DateFormatter.parseHttpDate(value);
} catch (Exception ignored) {
// `parseHttpDate()` can raise an exception rather than returning `null`
// when the given value has more than 64 characters.
}
if (date == null) {
throw new IllegalArgumentException("not a date: " + value);
}
return date.getTime();
}
@Test
public void testEncodingSingleCookieV0() throws ParseException {
final int maxAge = 50;
final String result = "myCookie=myValue; Max-Age=50; Expires=(.+?); Path=/apathsomewhere; " +
"Domain=.adomainsomewhere; Secure; SameSite=Strict";
final Cookie cookie = Cookie.builder("myCookie", "myValue")
.domain(".adomainsomewhere")
.maxAge(maxAge)
.path("/apathsomewhere")
.secure(true)
.sameSite("Strict")
.build();
final String encodedCookie = cookie.toSetCookieHeader();
final Matcher matcher = Pattern.compile(result).matcher(encodedCookie);
assertThat(matcher.find()).isTrue();
final Date expiresDate = DateFormatter.parseHttpDate(matcher.group(1));
final long diff = (expiresDate.getTime() - System.currentTimeMillis()) / 1000;
// 2 secs should be fine
assertThat(Math.abs(diff - maxAge)).isLessThanOrEqualTo(2);
}
@Test
void testDecodingSingleCookieV0() {
final String cookieString = "myCookie=myValue;expires=" +
DateFormatter.format(new Date(System.currentTimeMillis() + 50000)) +
";path=/apathsomewhere;domain=.adomainsomewhere;secure;";
final Cookie cookie = Cookie.fromSetCookieHeader(cookieString);
assertThat(cookie).isNotNull();
assertThat(cookie.value()).isEqualTo("myValue");
assertThat(cookie.domain()).isEqualTo(".adomainsomewhere");
assertThat(cookie.maxAge()).withFailMessage("maxAge should be defined when parsing cookie: " +
cookieString)
.isNotEqualTo(Cookie.UNDEFINED_MAX_AGE);
assertThat(cookie.maxAge()).withFailMessage("maxAge should be about 50ms when parsing cookie: " +
cookieString)
.isGreaterThanOrEqualTo(40)
.isLessThanOrEqualTo(60);
assertThat(cookie.path()).isEqualTo("/apathsomewhere");
assertThat(cookie.isSecure()).isTrue();
}
private long mergeMaxAgeAndExpires() {
// max age has precedence over expires
if (maxAge != Long.MIN_VALUE) {
return maxAge;
} else if (isValueDefined(expiresStart, expiresEnd)) {
Date expiresDate = DateFormatter.parseHttpDate(header, expiresStart, expiresEnd);
if (expiresDate != null) {
long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();
return maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0);
}
}
return Long.MIN_VALUE;
}
/**
* @deprecated Use {@link #getTimeMillis(CharSequence)} instead.
*
* Returns the date header value with the specified header name. If
* there are more than one header value for the specified header name, the
* first value is returned.
*
* @return the header value
* @throws ParseException
* if there is no such header or the header value is not a formatted date
*/
@Deprecated
public static Date getDateHeader(HttpMessage message, CharSequence name) throws ParseException {
String value = message.headers().get(name);
if (value == null) {
throw new ParseException("header not found: " + name, 0);
}
Date date = DateFormatter.parseHttpDate(value);
if (date == null) {
throw new ParseException("header can't be parsed into a Date: " + value, 0);
}
return date;
}
/**
* @deprecated Use {@link #set(CharSequence, Object)} instead.
*
* Sets a new date header with the specified name and value. If there
* is an existing header with the same name, the existing header is removed.
* The specified value is formatted as defined in
* <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1">RFC2616</a>
*/
@Deprecated
public static void setDateHeader(HttpMessage message, CharSequence name, Date value) {
if (value != null) {
message.headers().set(name, DateFormatter.format(value));
} else {
message.headers().set(name, null);
}
}
@Override
public CharSequence convertObject(Object value) {
if (value instanceof CharSequence) {
return (CharSequence) value;
}
if (value instanceof Date) {
return DateFormatter.format((Date) value);
}
if (value instanceof Calendar) {
return DateFormatter.format(((Calendar) value).getTime());
}
return value.toString();
}
private long mergeMaxAgeAndExpires() {
// max age has precedence over expires
if (maxAge != Long.MIN_VALUE) {
return maxAge;
} else if (isValueDefined(expiresStart, expiresEnd)) {
Date expiresDate = DateFormatter.parseHttpDate(header, expiresStart, expiresEnd);
if (expiresDate != null) {
long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();
return maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0);
}
}
return Long.MIN_VALUE;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("length", length)
.add("lastModified", DateFormatter.format(new Date(lastModifiedMillis)))
.toString();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this).omitNullValues()
.add("content", content())
.add("contentType", contentType())
.add("lastModified", DateFormatter.format(new Date(attrs.lastModifiedMillis())))
.add("dateEnabled", isDateEnabled())
.add("lastModifiedEnabled", isLastModifiedEnabled())
.add("headers", headers())
.toString();
}
private static void mergeMaxAgeAndExpires(CookieBuilder builder, String header) {
// max age has precedence over expires
if (builder.maxAge != Cookie.UNDEFINED_MAX_AGE) {
return;
}
if (isValueDefined(builder.expiresStart, builder.expiresEnd)) {
final Date expiresDate =
DateFormatter.parseHttpDate(header, builder.expiresStart, builder.expiresEnd);
if (expiresDate != null) {
final long maxAgeMillis = expiresDate.getTime() - System.currentTimeMillis();
builder.maxAge(maxAgeMillis / 1000 + (maxAgeMillis % 1000 != 0 ? 1 : 0));
}
}
}
@Nullable
@Override
@SuppressWarnings("UseOfObsoleteDateTimeApi")
public String convertObject(@Nullable Object value) {
if (value == null) {
return null;
}
// Try the types that appears more often first.
if (value instanceof CharSequence ||
value instanceof Number ||
value instanceof MediaType) {
return value.toString();
}
if (value instanceof Instant) {
return DateFormatter.format(new Date(((Instant) value).toEpochMilli()));
}
if (value instanceof TemporalAccessor) {
return DateFormatter.format(new Date(Instant.from((TemporalAccessor) value).toEpochMilli()));
}
if (value instanceof CacheControl) {
return ((CacheControl) value).asHeaderValue();
}
// Obsolete types.
if (value instanceof Date) {
return DateFormatter.format((Date) value);
}
if (value instanceof Calendar) {
return DateFormatter.format(((Calendar) value).getTime());
}
return value.toString();
}
private static void assert200Ok(CloseableHttpResponse res,
@Nullable String expectedContentType,
Consumer<String> contentAssertions) throws Exception {
assertStatusLine(res, "HTTP/1.1 200 OK");
// Ensure that the 'Date' header exists and is well-formed.
final String date = headerOrNull(res, HttpHeaders.DATE);
assertThat(date).isNotNull();
DateFormatter.parseHttpDate(date);
// Ensure that the 'Last-Modified' header exists and is well-formed.
final String lastModified = headerOrNull(res, HttpHeaders.LAST_MODIFIED);
assertThat(lastModified).isNotNull();
DateFormatter.parseHttpDate(lastModified);
// Ensure that the 'ETag' header exists and is well-formed.
final String entityTag = headerOrNull(res, HttpHeaders.ETAG);
assertThat(entityTag).matches(ETAG_PATTERN);
// Ensure the content type is correct.
if (expectedContentType != null) {
assertThat(headerOrNull(res, HttpHeaders.CONTENT_TYPE)).startsWith(expectedContentType);
} else {
assertThat(res.containsHeader(HttpHeaders.CONTENT_TYPE)).isFalse();
}
// Ensure the content satisfies the condition.
contentAssertions.accept(EntityUtils.toString(res.getEntity()).trim());
}
/**
* Encodes the specified cookie into a Set-Cookie header value.将指定的cookie编码为Set-Cookie标头值。
*
* @param cookie the cookie
* @return a single Set-Cookie header value
*/
public String encode(Cookie cookie) {
final String name = checkNotNull(cookie, "cookie").name();
final String value = cookie.value() != null ? cookie.value() : "";
validateCookie(name, value);
StringBuilder buf = stringBuilder();
if (cookie.wrap()) {
addQuoted(buf, name, value);
} else {
add(buf, name, value);
}
if (cookie.maxAge() != Long.MIN_VALUE) {
add(buf, CookieHeaderNames.MAX_AGE, cookie.maxAge());
Date expires = new Date(cookie.maxAge() * 1000 + System.currentTimeMillis());
buf.append(CookieHeaderNames.EXPIRES);
buf.append((char) HttpConstants.EQUALS);
DateFormatter.append(expires, buf);
buf.append((char) HttpConstants.SEMICOLON);
buf.append((char) HttpConstants.SP);
}
if (cookie.path() != null) {
add(buf, CookieHeaderNames.PATH, cookie.path());
}
if (cookie.domain() != null) {
add(buf, CookieHeaderNames.DOMAIN, cookie.domain());
}
if (cookie.isSecure()) {
add(buf, CookieHeaderNames.SECURE);
}
if (cookie.isHttpOnly()) {
add(buf, CookieHeaderNames.HTTPONLY);
}
return stripTrailingSeparator(buf);
}
@Override
public String convertTimeMillis(long value) {
return DateFormatter.format(new Date(value));
}
/**
* Encodes the specified {@link Cookie} into a {@code "Set-Cookie"} header value.
*
* @param strict whether to validate that name and value chars are in the valid scope defined in RFC 6265.
* @param cookie the {@link Cookie} to encode.
* @return a single {@code "Set-Cookie"} header value.
*/
static String encode(boolean strict, Cookie cookie) {
final String name = requireNonNull(cookie, "cookie").name();
final String value = firstNonNull(cookie.value(), "");
validateCookie(strict, name, value);
final StringBuilder buf = stringBuilder();
if (cookie.isValueQuoted()) {
addQuoted(buf, name, value);
} else {
add(buf, name, value);
}
if (cookie.maxAge() != Long.MIN_VALUE) {
add(buf, CookieHeaderNames.MAX_AGE, cookie.maxAge());
final Date expires = new Date(cookie.maxAge() * 1000 + System.currentTimeMillis());
buf.append(CookieHeaderNames.EXPIRES);
buf.append('=');
DateFormatter.append(expires, buf);
buf.append(';');
buf.append(HttpConstants.SP_CHAR);
}
final String path = cookie.path();
if (path != null) {
add(buf, CookieHeaderNames.PATH, path);
}
final String domain = cookie.domain();
if (domain != null) {
add(buf, CookieHeaderNames.DOMAIN, domain);
}
if (cookie.isSecure()) {
add(buf, CookieHeaderNames.SECURE);
}
if (cookie.isHttpOnly()) {
add(buf, CookieHeaderNames.HTTPONLY);
}
final String sameSite = cookie.sameSite();
if (sameSite != null) {
add(buf, "SameSite", sameSite);
}
return stripTrailingSeparator(buf);
}
/**
* @deprecated Use {@link #getTimeMillis(CharSequence, long)} instead.
*
* Returns the date header value with the specified header name. If
* there are more than one header value for the specified header name, the
* first value is returned.
*
* @return the header value or the {@code defaultValue} if there is no such
* header or the header value is not a formatted date
*/
@Deprecated
public static Date getDateHeader(HttpMessage message, CharSequence name, Date defaultValue) {
final String value = getHeader(message, name);
Date date = DateFormatter.parseHttpDate(value);
return date != null ? date : defaultValue;
}