/* * Copyright 2002-2016 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. * 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 org.springframework.http; import java.net.InetSocketAddress; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collections; import java.util.EnumSet; import java.util.GregorianCalendar; import java.util.List; import java.util.Locale; import java.util.TimeZone; import org.hamcrest.Matchers; import org.junit.Test; 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; /** * Unit tests for {@link org.springframework.http.HttpHeaders}. * * @author Arjen Poutsma * @author Sebastien Deleuze * @author Brian Clozel */ public class HttpHeadersTests { private final HttpHeaders headers = new HttpHeaders(); @Test public void getFirst() { headers.add(HttpHeaders.CACHE_CONTROL, "max-age=1000, public"); headers.add(HttpHeaders.CACHE_CONTROL, "s-maxage=1000"); assertThat(headers.getFirst(HttpHeaders.CACHE_CONTROL), is("max-age=1000, public")); } @Test public void accept() { MediaType mediaType1 = new MediaType("text", "html"); MediaType mediaType2 = new MediaType("text", "plain"); List<MediaType> mediaTypes = new ArrayList<>(2); mediaTypes.add(mediaType1); mediaTypes.add(mediaType2); headers.setAccept(mediaTypes); assertEquals("Invalid Accept header", mediaTypes, headers.getAccept()); assertEquals("Invalid Accept header", "text/html, text/plain", headers.getFirst("Accept")); } @Test // SPR-9655 public void acceptWithMultipleHeaderValues() { headers.add("Accept", "text/html"); headers.add("Accept", "text/plain"); List<MediaType> expected = Arrays.asList(new MediaType("text", "html"), new MediaType("text", "plain")); assertEquals("Invalid Accept header", expected, headers.getAccept()); } @Test // SPR-14506 public void acceptWithMultipleCommaSeparatedHeaderValues() { headers.add("Accept", "text/html,text/pdf"); headers.add("Accept", "text/plain,text/csv"); List<MediaType> expected = Arrays.asList(new MediaType("text", "html"), new MediaType("text", "pdf"), new MediaType("text", "plain"), new MediaType("text", "csv")); assertEquals("Invalid Accept header", expected, headers.getAccept()); } @Test public void acceptCharsets() { Charset charset1 = StandardCharsets.UTF_8; Charset charset2 = StandardCharsets.ISO_8859_1; List<Charset> charsets = new ArrayList<>(2); charsets.add(charset1); charsets.add(charset2); headers.setAcceptCharset(charsets); assertEquals("Invalid Accept header", charsets, headers.getAcceptCharset()); assertEquals("Invalid Accept header", "utf-8, iso-8859-1", headers.getFirst("Accept-Charset")); } @Test public void acceptCharsetWildcard() { headers.set("Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); assertEquals("Invalid Accept header", Arrays.asList(StandardCharsets.ISO_8859_1, StandardCharsets.UTF_8), headers.getAcceptCharset()); } @Test public void allow() { EnumSet<HttpMethod> methods = EnumSet.of(HttpMethod.GET, HttpMethod.POST); headers.setAllow(methods); assertEquals("Invalid Allow header", methods, headers.getAllow()); assertEquals("Invalid Allow header", "GET,POST", headers.getFirst("Allow")); } @Test public void contentLength() { long length = 42L; headers.setContentLength(length); assertEquals("Invalid Content-Length header", length, headers.getContentLength()); assertEquals("Invalid Content-Length header", "42", headers.getFirst("Content-Length")); } @Test public void contentType() { MediaType contentType = new MediaType("text", "html", StandardCharsets.UTF_8); headers.setContentType(contentType); assertEquals("Invalid Content-Type header", contentType, headers.getContentType()); assertEquals("Invalid Content-Type header", "text/html;charset=UTF-8", headers.getFirst("Content-Type")); } @Test public void location() throws URISyntaxException { URI location = new URI("http://www.example.com/hotels"); headers.setLocation(location); assertEquals("Invalid Location header", location, headers.getLocation()); assertEquals("Invalid Location header", "http://www.example.com/hotels", headers.getFirst("Location")); } @Test public void eTag() { String eTag = "\"v2.6\""; headers.setETag(eTag); assertEquals("Invalid ETag header", eTag, headers.getETag()); assertEquals("Invalid ETag header", "\"v2.6\"", headers.getFirst("ETag")); } @Test public void host() { InetSocketAddress host = InetSocketAddress.createUnresolved("localhost", 8080); headers.setHost(host); assertEquals("Invalid Host header", host, headers.getHost()); assertEquals("Invalid Host header", "localhost:8080", headers.getFirst("Host")); } @Test public void hostNoPort() { InetSocketAddress host = InetSocketAddress.createUnresolved("localhost", 0); headers.setHost(host); assertEquals("Invalid Host header", host, headers.getHost()); assertEquals("Invalid Host header", "localhost", headers.getFirst("Host")); } @Test(expected = IllegalArgumentException.class) public void illegalETag() { String eTag = "v2.6"; headers.setETag(eTag); assertEquals("Invalid ETag header", eTag, headers.getETag()); assertEquals("Invalid ETag header", "\"v2.6\"", headers.getFirst("ETag")); } @Test public void ifMatch() { String ifMatch = "\"v2.6\""; headers.setIfMatch(ifMatch); assertEquals("Invalid If-Match header", ifMatch, headers.getIfMatch().get(0)); assertEquals("Invalid If-Match header", "\"v2.6\"", headers.getFirst("If-Match")); } @Test(expected = IllegalArgumentException.class) public void ifMatchIllegalHeader() { headers.setIfMatch("Illegal"); headers.getIfMatch(); } @Test public void ifMatchMultipleHeaders() { headers.add(HttpHeaders.IF_MATCH, "\"v2,0\""); headers.add(HttpHeaders.IF_MATCH, "W/\"v2,1\", \"v2,2\""); assertEquals("Invalid If-Match header", "\"v2,0\"", headers.get(HttpHeaders.IF_MATCH).get(0)); assertEquals("Invalid If-Match header", "W/\"v2,1\", \"v2,2\"", headers.get(HttpHeaders.IF_MATCH).get(1)); assertThat(headers.getIfMatch(), Matchers.contains("\"v2,0\"", "W/\"v2,1\"", "\"v2,2\"")); } @Test public void ifNoneMatch() { String ifNoneMatch = "\"v2.6\""; headers.setIfNoneMatch(ifNoneMatch); assertEquals("Invalid If-None-Match header", ifNoneMatch, headers.getIfNoneMatch().get(0)); assertEquals("Invalid If-None-Match header", "\"v2.6\"", headers.getFirst("If-None-Match")); } @Test public void ifNoneMatchWildCard() { String ifNoneMatch = "*"; headers.setIfNoneMatch(ifNoneMatch); assertEquals("Invalid If-None-Match header", ifNoneMatch, headers.getIfNoneMatch().get(0)); assertEquals("Invalid If-None-Match header", "*", headers.getFirst("If-None-Match")); } @Test public void ifNoneMatchList() { String ifNoneMatch1 = "\"v2.6\""; String ifNoneMatch2 = "\"v2.7\", \"v2.8\""; List<String> ifNoneMatchList = new ArrayList<>(2); ifNoneMatchList.add(ifNoneMatch1); ifNoneMatchList.add(ifNoneMatch2); headers.setIfNoneMatch(ifNoneMatchList); assertThat(headers.getIfNoneMatch(), Matchers.contains("\"v2.6\"", "\"v2.7\"", "\"v2.8\"")); assertEquals("Invalid If-None-Match header", "\"v2.6\", \"v2.7\", \"v2.8\"", headers.getFirst("If-None-Match")); } @Test public void date() { Calendar calendar = new GregorianCalendar(2008, 11, 18, 11, 20); calendar.setTimeZone(TimeZone.getTimeZone("CET")); long date = calendar.getTimeInMillis(); headers.setDate(date); assertEquals("Invalid Date header", date, headers.getDate()); assertEquals("Invalid Date header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("date")); // RFC 850 headers.set("Date", "Thu, 18 Dec 2008 10:20:00 GMT"); assertEquals("Invalid Date header", date, headers.getDate()); } @Test(expected = IllegalArgumentException.class) public void dateInvalid() { headers.set("Date", "Foo Bar Baz"); headers.getDate(); } @Test public void dateOtherLocale() { Locale defaultLocale = Locale.getDefault(); try { Locale.setDefault(new Locale("nl", "nl")); Calendar calendar = new GregorianCalendar(2008, 11, 18, 11, 20); calendar.setTimeZone(TimeZone.getTimeZone("CET")); long date = calendar.getTimeInMillis(); headers.setDate(date); assertEquals("Invalid Date header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("date")); assertEquals("Invalid Date header", date, headers.getDate()); } finally { Locale.setDefault(defaultLocale); } } @Test public void lastModified() { Calendar calendar = new GregorianCalendar(2008, 11, 18, 11, 20); calendar.setTimeZone(TimeZone.getTimeZone("CET")); long date = calendar.getTimeInMillis(); headers.setLastModified(date); assertEquals("Invalid Last-Modified header", date, headers.getLastModified()); assertEquals("Invalid Last-Modified header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("last-modified")); } @Test public void expires() { Calendar calendar = new GregorianCalendar(2008, 11, 18, 11, 20); calendar.setTimeZone(TimeZone.getTimeZone("CET")); long date = calendar.getTimeInMillis(); headers.setExpires(date); assertEquals("Invalid Expires header", date, headers.getExpires()); assertEquals("Invalid Expires header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("expires")); } @Test // SPR-10648 (example is from INT-3063) public void expiresInvalidDate() { headers.set("Expires", "-1"); assertEquals(-1, headers.getExpires()); } @Test public void ifModifiedSince() { Calendar calendar = new GregorianCalendar(2008, 11, 18, 11, 20); calendar.setTimeZone(TimeZone.getTimeZone("CET")); long date = calendar.getTimeInMillis(); headers.setIfModifiedSince(date); assertEquals("Invalid If-Modified-Since header", date, headers.getIfModifiedSince()); assertEquals("Invalid If-Modified-Since header", "Thu, 18 Dec 2008 10:20:00 GMT", headers.getFirst("if-modified-since")); } @Test // SPR-14144 public void invalidIfModifiedSinceHeader() { headers.set(HttpHeaders.IF_MODIFIED_SINCE, "0"); assertEquals(-1, headers.getIfModifiedSince()); headers.set(HttpHeaders.IF_MODIFIED_SINCE, "-1"); assertEquals(-1, headers.getIfModifiedSince()); headers.set(HttpHeaders.IF_MODIFIED_SINCE, "XXX"); assertEquals(-1, headers.getIfModifiedSince()); } @Test public void pragma() { String pragma = "no-cache"; headers.setPragma(pragma); assertEquals("Invalid Pragma header", pragma, headers.getPragma()); assertEquals("Invalid Pragma header", "no-cache", headers.getFirst("pragma")); } @Test public void cacheControl() { String cacheControl = "no-cache"; headers.setCacheControl(cacheControl); assertEquals("Invalid Cache-Control header", cacheControl, headers.getCacheControl()); assertEquals("Invalid Cache-Control header", "no-cache", headers.getFirst("cache-control")); } @Test public void cacheControlAllValues() { headers.add(HttpHeaders.CACHE_CONTROL, "max-age=1000, public"); headers.add(HttpHeaders.CACHE_CONTROL, "s-maxage=1000"); assertThat(headers.getCacheControl(), is("max-age=1000, public, s-maxage=1000")); } @Test public void contentDisposition() { ContentDisposition disposition = headers.getContentDisposition(); assertNotNull(disposition); assertEquals("Invalid Content-Disposition header", ContentDisposition.empty(), headers.getContentDisposition()); disposition = ContentDisposition.builder("attachment").name("foo").filename("foo.txt").size(123L).build(); headers.setContentDisposition(disposition); assertEquals("Invalid Content-Disposition header", disposition, headers.getContentDisposition()); } @Test // SPR-11917 public void getAllowEmptySet() { headers.setAllow(Collections.<HttpMethod> emptySet()); assertThat(headers.getAllow(), Matchers.emptyCollectionOf(HttpMethod.class)); } @Test public void accessControlAllowCredentials() { assertFalse(headers.getAccessControlAllowCredentials()); headers.setAccessControlAllowCredentials(false); assertFalse(headers.getAccessControlAllowCredentials()); headers.setAccessControlAllowCredentials(true); assertTrue(headers.getAccessControlAllowCredentials()); } @Test public void accessControlAllowHeaders() { List<String> allowedHeaders = headers.getAccessControlAllowHeaders(); assertThat(allowedHeaders, Matchers.emptyCollectionOf(String.class)); headers.setAccessControlAllowHeaders(Arrays.asList("header1", "header2")); allowedHeaders = headers.getAccessControlAllowHeaders(); assertEquals(allowedHeaders, Arrays.asList("header1", "header2")); } @Test public void accessControlAllowHeadersMultipleValues() { List<String> allowedHeaders = headers.getAccessControlAllowHeaders(); assertThat(allowedHeaders, Matchers.emptyCollectionOf(String.class)); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "header1, header2"); headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "header3"); allowedHeaders = headers.getAccessControlAllowHeaders(); assertEquals(Arrays.asList("header1", "header2", "header3"), allowedHeaders); } @Test public void accessControlAllowMethods() { List<HttpMethod> allowedMethods = headers.getAccessControlAllowMethods(); assertThat(allowedMethods, Matchers.emptyCollectionOf(HttpMethod.class)); headers.setAccessControlAllowMethods(Arrays.asList(HttpMethod.GET, HttpMethod.POST)); allowedMethods = headers.getAccessControlAllowMethods(); assertEquals(allowedMethods, Arrays.asList(HttpMethod.GET, HttpMethod.POST)); } @Test public void accessControlAllowOrigin() { assertNull(headers.getAccessControlAllowOrigin()); headers.setAccessControlAllowOrigin("*"); assertEquals("*", headers.getAccessControlAllowOrigin()); } @Test public void accessControlExposeHeaders() { List<String> exposedHeaders = headers.getAccessControlExposeHeaders(); assertThat(exposedHeaders, Matchers.emptyCollectionOf(String.class)); headers.setAccessControlExposeHeaders(Arrays.asList("header1", "header2")); exposedHeaders = headers.getAccessControlExposeHeaders(); assertEquals(exposedHeaders, Arrays.asList("header1", "header2")); } @Test public void accessControlMaxAge() { assertEquals(-1, headers.getAccessControlMaxAge()); headers.setAccessControlMaxAge(3600); assertEquals(3600, headers.getAccessControlMaxAge()); } @Test public void accessControlRequestHeaders() { List<String> requestHeaders = headers.getAccessControlRequestHeaders(); assertThat(requestHeaders, Matchers.emptyCollectionOf(String.class)); headers.setAccessControlRequestHeaders(Arrays.asList("header1", "header2")); requestHeaders = headers.getAccessControlRequestHeaders(); assertEquals(requestHeaders, Arrays.asList("header1", "header2")); } @Test public void accessControlRequestMethod() { assertNull(headers.getAccessControlRequestMethod()); headers.setAccessControlRequestMethod(HttpMethod.POST); assertEquals(HttpMethod.POST, headers.getAccessControlRequestMethod()); } @Test public void acceptLanguage() { String headerValue = "fr-ch, fr;q=0.9, en-*;q=0.8, de;q=0.7, *;q=0.5"; headers.setAcceptLanguage(Locale.LanguageRange.parse(headerValue)); assertEquals(headerValue, headers.getFirst(HttpHeaders.ACCEPT_LANGUAGE)); List<Locale.LanguageRange> expectedRanges = Arrays.asList( new Locale.LanguageRange("fr-ch"), new Locale.LanguageRange("fr", 0.9), new Locale.LanguageRange("en-*", 0.8), new Locale.LanguageRange("de", 0.7), new Locale.LanguageRange("*", 0.5) ); assertEquals(expectedRanges, headers.getAcceptLanguage()); assertEquals(Locale.forLanguageTag("fr-ch"), headers.getAcceptLanguageAsLocales().get(0)); headers.setAcceptLanguageAsLocales(Collections.singletonList(Locale.FRANCE)); assertEquals(Locale.FRANCE, headers.getAcceptLanguageAsLocales().get(0)); } @Test public void contentLanguage() { headers.setContentLanguage(Locale.FRANCE); assertEquals(Locale.FRANCE, headers.getContentLanguage()); assertEquals("fr-FR", headers.getFirst(HttpHeaders.CONTENT_LANGUAGE)); } @Test public void contentLanguageSerialized() { headers.set(HttpHeaders.CONTENT_LANGUAGE, "de, en_CA"); assertEquals("Expected one (first) locale", Locale.GERMAN, headers.getContentLanguage()); } }