Overloaded convenience setters: setCacheControl(CacheControl), setExpires(ZonedDateTime)

Issue: SPR-16562
This commit is contained in:
Juergen Hoeller 2018-03-06 23:06:04 +01:00
parent 82515a3f01
commit 90d768bb7f
2 changed files with 76 additions and 43 deletions

View File

@ -48,7 +48,6 @@ import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
/**
* Represents HTTP request and response headers, mapping string header names to a list of string values.
*
@ -472,8 +471,8 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* {@link #getAcceptLanguageAsLocales()} or if you need to filter based on
* a list of supported locales you can pass the returned list to
* {@link Locale#filter(List, Collection)}.
* @since 5.0
* @throws IllegalArgumentException if the value cannot be converted to a language range
* @since 5.0
*/
public List<Locale.LanguageRange> getAcceptLanguage() {
String value = getFirst(ACCEPT_LANGUAGE);
@ -494,8 +493,8 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* A variant of {@link #getAcceptLanguage()} that converts each
* {@link java.util.Locale.LanguageRange} to a {@link Locale}.
* @return the locales or an empty list
* @since 5.0
* @throws IllegalArgumentException if the value cannot be converted to a locale
* @since 5.0
*/
public List<Locale> getAcceptLanguageAsLocales() {
List<Locale.LanguageRange> ranges = getAcceptLanguage();
@ -711,6 +710,15 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
}
}
/**
* Set a configured {@link CacheControl} instance as the
* new value of the {@code Cache-Control} header.
* @since 5.0.5
*/
public void setCacheControl(CacheControl cacheControl) {
set(CACHE_CONTROL, cacheControl.getHeaderValue());
}
/**
* Set the (new) value of the {@code Cache-Control} header.
*/
@ -907,6 +915,15 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
return getFirst(ETAG);
}
/**
* Set the duration after which the message is no longer valid,
* as specified by the {@code Expires} header.
* @since 5.0.5
*/
public void setExpires(ZonedDateTime expires) {
setZonedDateTime(EXPIRES, expires);
}
/**
* Set the date and time at which the message is no longer valid,
* as specified by the {@code Expires} header.
@ -932,13 +949,16 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* Set the (new) value of the {@code Host} header.
* <p>If the given {@linkplain InetSocketAddress#getPort() port} is {@code 0},
* the host header will only contain the
* {@linkplain InetSocketAddress#getHostString() hostname}.
* {@linkplain InetSocketAddress#getHostString() host name}.
* @since 5.0
*/
public void setHost(@Nullable InetSocketAddress host) {
if (host != null) {
String value = (host.getPort() != 0 ?
String.format("%s:%d", host.getHostString(), host.getPort()) : host.getHostString());
String value = host.getHostString();
int port = host.getPort();
if (port != 0) {
value = value + ":" + port;
}
set(HOST, value);
}
else {
@ -958,28 +978,25 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
if (value == null) {
return null;
}
final int idx;
if (value.startsWith("[")) {
idx = value.indexOf(':', value.indexOf(']'));
} else {
idx = value.lastIndexOf(':');
}
String hostname = null;
String host = null;
int port = 0;
if (idx != -1 && idx < value.length() - 1) {
hostname = value.substring(0, idx);
String portString = value.substring(idx + 1);
int separator = (value.startsWith("[") ? value.indexOf(':', value.indexOf(']')) : value.lastIndexOf(':'));
if (separator != -1) {
host = value.substring(0, separator);
String portString = value.substring(separator + 1);
try {
port = Integer.parseInt(portString);
}
catch (NumberFormatException ex) {
// ignored
// ignore
}
}
if (hostname == null) {
hostname = value;
if (host == null) {
host = value;
}
return InetSocketAddress.createUnresolved(hostname, port);
return InetSocketAddress.createUnresolved(host, port);
}
/**
@ -1188,6 +1205,16 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
return getValuesAsList(VARY);
}
/**
* Set the given date under the given header name after formatting it as a string
* using the RFC-1123 date-time formatter. The equivalent of
* {@link #set(String, String)} but for date headers.
* @since 5.0
*/
public void setZonedDateTime(String headerName, ZonedDateTime date) {
set(headerName, DATE_FORMATTERS[0].format(date));
}
/**
* Set the given date under the given header name after formatting it as a string
* using the RFC-1123 date-time formatter. The equivalent of
@ -1201,16 +1228,6 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
set(headerName, DATE_FORMATTERS[0].format(zonedDateTime));
}
/**
* Set the given date under the given header name after formatting it as a string
* using the RFC-1123 date-time formatter. The equivalent of
* {@link #set(String, String)} but for date headers.
* @since 5.0
*/
public void setZonedDateTime(String headerName, ZonedDateTime date) {
set(headerName, DATE_FORMATTERS[0].format(date));
}
/**
* Parse the first header value for the given header name as a date,
* return -1 if there is no value, or raise {@link IllegalArgumentException}
@ -1549,7 +1566,7 @@ public class HttpHeaders implements MultiValueMap<String, String>, Serializable
* Return a {@code HttpHeaders} object that can only be read, not written to.
*/
public static HttpHeaders readOnlyHttpHeaders(HttpHeaders headers) {
return headers.readOnly ? headers : new HttpHeaders(headers, true);
return (headers.readOnly ? headers : new HttpHeaders(headers, true));
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +21,7 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.time.DateTimeException;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.ArrayList;
@ -37,13 +38,8 @@ import org.hamcrest.Matchers;
import org.junit.Test;
import static java.time.format.DateTimeFormatter.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
/**
* Unit tests for {@link org.springframework.http.HttpHeaders}.
@ -51,6 +47,7 @@ import static org.junit.Assert.assertTrue;
* @author Arjen Poutsma
* @author Sebastien Deleuze
* @author Brian Clozel
* @author Juergen Hoeller
*/
public class HttpHeadersTests {
@ -284,7 +281,7 @@ public class HttpHeadersTests {
}
@Test
public void expires() {
public void expiresLong() {
Calendar calendar = new GregorianCalendar(2008, 11, 18, 11, 20);
calendar.setTimeZone(TimeZone.getTimeZone("CET"));
long date = calendar.getTimeInMillis();
@ -293,6 +290,19 @@ public class HttpHeadersTests {
assertEquals("Invalid Expires header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("expires"));
}
@Test
public void expiresZonedDateTime() {
ZonedDateTime zonedDateTime = ZonedDateTime.of(2008, 12, 18, 10, 20, 0, 0, ZoneId.of("GMT"));
headers.setExpires(zonedDateTime);
assertEquals("Invalid Expires header", zonedDateTime.toInstant().toEpochMilli(), headers.getExpires());
assertEquals("Invalid Expires header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("expires"));
}
@Test(expected = DateTimeException.class) // SPR-16560
public void expiresLargeDate() {
headers.setExpires(Long.MAX_VALUE);
}
@Test // SPR-10648 (example is from INT-3063)
public void expiresInvalidDate() {
headers.set("Expires", "-1");
@ -332,9 +342,15 @@ public class HttpHeadersTests {
@Test
public void cacheControl() {
String cacheControl = "no-cache";
headers.setCacheControl(cacheControl);
assertEquals("Invalid Cache-Control header", cacheControl, headers.getCacheControl());
headers.setCacheControl("no-cache");
assertEquals("Invalid Cache-Control header", "no-cache", headers.getCacheControl());
assertEquals("Invalid Cache-Control header", "no-cache", headers.getFirst("cache-control"));
}
@Test
public void cacheControlBuilder() {
headers.setCacheControl(CacheControl.noCache());
assertEquals("Invalid Cache-Control header", "no-cache", headers.getCacheControl());
assertEquals("Invalid Cache-Control header", "no-cache", headers.getFirst("cache-control"));
}