Top Description Fields Constructors Methods
org.springframework.http

public Class HttpHeaders

extends Object
implements MultiValueMap<String, String>, Serializable
Class Inheritance
All Implemented Interfaces
java.io.Serializable, org.springframework.util.MultiValueMap, java.util.Map
Known Direct Subclasses
org.springframework.http.ReadOnlyHttpHeaders, org.springframework.http.server.ServletServerHttpResponse.ServletResponseHttpHeaders
Imports
java.io.Serializable, java.net.InetSocketAddress, .URI, java.nio.charset.Charset, .CharsetEncoder, .StandardCharsets, java.text.DecimalFormat, .DecimalFormatSymbols, java.time.Duration, .Instant, .ZoneId, .ZonedDateTime, java.time.format.DateTimeFormatter, .DateTimeParseException, java.util.ArrayList, .Base64, .Collection, .Collections, .LinkedHashSet, .List, .Locale, .Map, .Set, .StringJoiner, java.util.function.BiConsumer, java.util.regex.Matcher, .Pattern, java.util.stream.Collectors, org.springframework.lang.Nullable, org.springframework.util.Assert, .CollectionUtils, .LinkedCaseInsensitiveMap, .LinkedMultiValueMap, .MultiValueMap, .StringUtils

A data structure representing HTTP request or response headers, mapping String header names to a list of String values, also offering accessors for common application-level data types.

In addition to the regular methods defined by Map, this class offers many common convenience methods, for example:

Note that HttpHeaders generally treats header names in a case-insensitive manner.

Authors
Arjen Poutsma, Sebastien Deleuze, Brian Clozel, Juergen Hoeller, Josh Long, Sam Brannen
Since
3.0

Field Summary

Modifier and TypeField and Description
public static final String
ACCEPT

The HTTP Accept header field name.

public static final String
ACCEPT_CHARSET

The HTTP Accept-Charset header field name.

public static final String
ACCEPT_ENCODING

The HTTP Accept-Encoding header field name.

public static final String
ACCEPT_LANGUAGE

The HTTP Accept-Language header field name.

public static final String
ACCEPT_PATCH

The HTTP Accept-Patch header field name.

public static final String
ACCEPT_RANGES

The HTTP Accept-Ranges header field name.

public static final String
ACCESS_CONTROL_ALLOW_CREDENTIALS

The CORS Access-Control-Allow-Credentials response header field name.

public static final String
ACCESS_CONTROL_ALLOW_HEADERS

The CORS Access-Control-Allow-Headers response header field name.

public static final String
ACCESS_CONTROL_ALLOW_METHODS

The CORS Access-Control-Allow-Methods response header field name.

public static final String
ACCESS_CONTROL_ALLOW_ORIGIN

The CORS Access-Control-Allow-Origin response header field name.

public static final String
ACCESS_CONTROL_EXPOSE_HEADERS

The CORS Access-Control-Expose-Headers response header field name.

public static final String
ACCESS_CONTROL_MAX_AGE

The CORS Access-Control-Max-Age response header field name.

public static final String
ACCESS_CONTROL_REQUEST_HEADERS

The CORS Access-Control-Request-Headers request header field name.

public static final String
ACCESS_CONTROL_REQUEST_METHOD

The CORS Access-Control-Request-Method request header field name.

public static final String
AGE

The HTTP Age header field name.

public static final String
ALLOW

The HTTP Allow header field name.

public static final String
AUTHORIZATION

The HTTP Authorization header field name.

public static final String
CACHE_CONTROL

The HTTP Cache-Control header field name.

public static final String
CONNECTION

The HTTP Connection header field name.

public static final String
CONTENT_DISPOSITION

The HTTP Content-Disposition header field name.

public static final String
CONTENT_ENCODING

The HTTP Content-Encoding header field name.

public static final String
CONTENT_LANGUAGE

The HTTP Content-Language header field name.

public static final String
CONTENT_LENGTH

The HTTP Content-Length header field name.

public static final String
CONTENT_LOCATION

The HTTP Content-Location header field name.

public static final String
CONTENT_RANGE

The HTTP Content-Range header field name.

public static final String
CONTENT_TYPE

The HTTP Content-Type header field name.

public static final String
COOKIE

The HTTP Cookie header field name.

public static final String
DATE

The HTTP Date header field name.

private static final DateTimeFormatter
DATE_FORMATTER

Date formats with time zone as specified in the HTTP RFC to use for formatting.

private static final DateTimeFormatter[]
DATE_PARSERS

Date formats with time zone as specified in the HTTP RFC to use for parsing.

private static final DecimalFormatSymbols
public static final HttpHeaders
EMPTY

An empty HttpHeaders instance (immutable).

public static final String
ETAG

The HTTP ETag header field name.

private static final Pattern
ETAG_HEADER_VALUE_PATTERN

Pattern matching ETag multiple field values in headers such as "If-Match", "If-None-Match".

public static final String
EXPECT

The HTTP Expect header field name.

public static final String
EXPIRES

The HTTP Expires header field name.

public static final String
FROM

The HTTP From header field name.

private static final ZoneId
pack-priv final MultiValueMap<String, String>
public static final String
HOST

The HTTP Host header field name.

public static final String
IF_MATCH

The HTTP If-Match header field name.

public static final String
IF_MODIFIED_SINCE

The HTTP If-Modified-Since header field name.

public static final String
IF_NONE_MATCH

The HTTP If-None-Match header field name.

public static final String
IF_RANGE

The HTTP If-Range header field name.

public static final String
IF_UNMODIFIED_SINCE

The HTTP If-Unmodified-Since header field name.

public static final String
LAST_MODIFIED

The HTTP Last-Modified header field name.

public static final String
LINK

The HTTP Link header field name.

public static final String
LOCATION

The HTTP Location header field name.

public static final String
MAX_FORWARDS

The HTTP Max-Forwards header field name.

public static final String
ORIGIN

The HTTP Origin header field name.

public static final String
PRAGMA

The HTTP Pragma header field name.

public static final String
PROXY_AUTHENTICATE

The HTTP Proxy-Authenticate header field name.

public static final String
PROXY_AUTHORIZATION

The HTTP Proxy-Authorization header field name.

public static final String
RANGE

The HTTP Range header field name.

public static final String
REFERER

The HTTP Referer header field name.

public static final String
RETRY_AFTER

The HTTP Retry-After header field name.

private static final long
public static final String
SERVER

The HTTP Server header field name.

public static final String
SET_COOKIE

The HTTP Set-Cookie header field name.

public static final String
SET_COOKIE2

The HTTP Set-Cookie2 header field name.

public static final String
TE

The HTTP TE header field name.

public static final String
TRAILER

The HTTP Trailer header field name.

public static final String
TRANSFER_ENCODING

The HTTP Transfer-Encoding header field name.

public static final String
UPGRADE

The HTTP Upgrade header field name.

public static final String
USER_AGENT

The HTTP User-Agent header field name.

public static final String
VARY

The HTTP Vary header field name.

public static final String
VIA

The HTTP Via header field name.

public static final String
WARNING

The HTTP Warning header field name.

public static final String
WWW_AUTHENTICATE

The HTTP WWW-Authenticate header field name.

Constructor Summary

AccessConstructor and Description
public
HttpHeaders()

Construct a new, empty instance of the HttpHeaders object.

public
HttpHeaders(MultiValueMap<String, String>
the headers map (expected to operate with case-insensitive keys)
headers
)

Construct a new HttpHeaders instance backed by an existing map.

Method Summary

Modifier and TypeMethod and Description
public void
add(String
the header name
headerName
,
String
the header value
headerValue
)

Implements org.springframework.util.MultiValueMap.add.

Add the given, single header value under the given name.

public void
addAll(String
they key
key
,
List<? extends String>
the values to be added
values
)

Implements org.springframework.util.MultiValueMap.addAll.

Add all the values of the given list to the current list of values for the given key.

public void
addAll(MultiValueMap<String, String>
the values to be added
values
)

Implements org.springframework.util.MultiValueMap.addAll.

Add all the values of the given MultiValueMap to the current values.

private static void
addToken(StringBuilder builder, List<String> tokens, boolean trim)

public void
clear()

Implements java.util.Map.clear.

Removes all of the mappings from this map (optional operation).

public void
clearContentHeaders()

Remove the well-known "Content-*" HTTP headers.

public boolean
containsKey(Object
key whose presence in this map is to be tested
key
)

Implements java.util.Map.containsKey.

Returns true if this map contains a mapping for the specified key.

public boolean
containsValue(Object
value whose presence in this map is to be tested
value
)

Implements java.util.Map.containsValue.

Returns true if this map maps one or more keys to the specified value.

public static String
encodeBasicAuth(String
the username
username
,
String
the password
password
,
Charset
the charset to use to convert the credentials into an octet sequence. Defaults to ISO-8859-1.
charset
)

Encode the given username and password into Basic Authentication credentials.

public Set<Map.Entry<String, List<String>>>
entrySet()

Implements java.util.Map.entrySet.

Returns a Set view of the mappings contained in this map.

public boolean
equals(Object
object to be compared for equality with this map
other
)

Overrides java.lang.Object.equals.

Implements java.util.Map.equals.

Compares the specified object with this map for equality.

public void
forEach(BiConsumer<? super String, ? super List<String>>
The action to be performed for each entry
action
)

Overrides default java.util.Map.forEach.

Performs the given action for each entry in this map until all entries have been processed or the action throws an exception.

pack-priv static String
formatDate(long date)

public static String

Returns:

the headers to a String
formatHeaders
(MultiValueMap<String, String>
the headers to format
headers
)

Helps to format HTTP header values, as HTTP header values themselves can contain comma-separated values, can become confusing with regular Map formatting that also uses commas between entries.

public List<String>
get(Object
the key whose associated value is to be returned
key
)

Implements java.util.Map.get.

Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

public List<MediaType>
getAccept()

Return the list of acceptable media types, as specified by the Accept header.

public List<Charset>
getAcceptCharset()

Return the list of acceptable charsets, as specified by the Accept-Charset header.

public List<Locale.LanguageRange>
getAcceptLanguage()

Return the language ranges from the "Accept-Language" header.

public List<Locale>

Returns:

the locales or an empty list
getAcceptLanguageAsLocales
()

A variant of getAcceptLanguage() that converts each java.util.Locale.LanguageRange to a Locale.

public List<MediaType>
getAcceptPatch()

Return the list of acceptable media types for PATCH methods, as specified by the Accept-Patch header.

public boolean
getAccessControlAllowCredentials()

Return the value of the Access-Control-Allow-Credentials response header.

public List<String>
getAccessControlAllowHeaders()

Return the value of the Access-Control-Allow-Headers response header.

public List<HttpMethod>
getAccessControlAllowMethods()

Return the value of the Access-Control-Allow-Methods response header.

public String
getAccessControlAllowOrigin()

Return the value of the Access-Control-Allow-Origin response header.

public List<String>
getAccessControlExposeHeaders()

Return the value of the Access-Control-Expose-Headers response header.

public long
getAccessControlMaxAge()

Return the value of the Access-Control-Max-Age response header.

public List<String>
getAccessControlRequestHeaders()

Return the value of the Access-Control-Request-Headers request header.

public HttpMethod
getAccessControlRequestMethod()

Return the value of the Access-Control-Request-Method request header.

public Set<HttpMethod>
getAllow()

Return the set of allowed HTTP methods, as specified by the Allow header.

public String
getCacheControl()

Return the value of the Cache-Control header.

public List<String>
getConnection()

Return the value of the Connection header.

public ContentDisposition
getContentDisposition()

Return a parsed representation of the Content-Disposition header.

public Locale

Returns:

the first Locale of the content languages, or null if unknown
getContentLanguage
()

Get the first Locale of the content languages, as specified by the Content-Language header.

public long
getContentLength()

Return the length of the body in bytes, as specified by the Content-Length header.

public MediaType
getContentType()

Return the media type of the body, as specified by the Content-Type header.

public long
getDate()

Return the date and time at which the message was created, as specified by the Date header.

public String
getETag()

Return the entity tag of the body, as specified by the ETag header.

protected List<String>

Returns:

the combined result
getETagValuesAsList
(String
the header name
headerName
)

Retrieve a combined result from the field values of the ETag header.

public long
getExpires()

Return the date and time at which the message is no longer valid, as specified by the Expires header.

protected String

Returns:

the combined result
getFieldValues
(String
the header name
headerName
)

Retrieve a combined result from the field values of multivalued headers.

public String

Returns:

the first header value, or null if none
getFirst
(String
the header name
headerName
)

Implements org.springframework.util.MultiValueMap.getFirst.

Return the first header value for the given header name, if any.

public long

Returns:

the parsed date header, or -1 if none
getFirstDate
(String
the header name
headerName
)

Parse the first header value for the given header name as a date, return -1 if there is no value, or raise IllegalArgumentException if the value cannot be parsed as a date.

private long

Returns:

the parsed date header, or -1 if none (or invalid)
getFirstDate
(String
the header name
headerName
,
boolean
whether to reject invalid values with an IllegalArgumentException (true) or rather return -1 in that case (false)
rejectInvalid
)

Parse the first header value for the given header name as a date, return -1 if there is no value or also in case of an invalid value (if rejectInvalid=false), or raise IllegalArgumentException if the value cannot be parsed as a date.

public ZonedDateTime

Returns:

the parsed date header, or null if none
getFirstZonedDateTime
(String
the header name
headerName
)

Parse the first header value for the given header name as a date, return null if there is no value, or raise IllegalArgumentException if the value cannot be parsed as a date.

private ZonedDateTime

Returns:

the parsed date header, or null if none (or invalid)
getFirstZonedDateTime
(String
the header name
headerName
,
boolean
whether to reject invalid values with an IllegalArgumentException (true) or rather return null in that case (false)
rejectInvalid
)

Parse the first header value for the given header name as a date, return null if there is no value or also in case of an invalid value (if rejectInvalid=false), or raise IllegalArgumentException if the value cannot be parsed as a date.

public InetSocketAddress
getHost()

Return the value of the Host header, if available.

public List<String>
getIfMatch()

Return the value of the If-Match header.

public long
getIfModifiedSince()

Return the value of the If-Modified-Since header.

public List<String>
getIfNoneMatch()

Return the value of the If-None-Match header.

public long
getIfUnmodifiedSince()

Return the value of the If-Unmodified-Since header.

public long
getLastModified()

Return the time the resource was last changed, as specified by the Last-Modified header.

public URI
getLocation()

Return the (new) location of a resource as specified by the Location header.

public List<String>

Returns:

the list of header values, or an empty list
getOrEmpty
(Object
the header name
headerName
)

Get the list of header values for the given header name, if any.

public String
getOrigin()

Return the value of the Origin header.

public String
getPragma()

Return the value of the Pragma header.

public List<HttpRange>
getRange()

Return the value of the Range header.

public String
getUpgrade()

Return the value of the Upgrade header.

public List<String>

Returns:

all associated values
getValuesAsList
(String
the header name
headerName
)

Return all values of a given header name, even if this header is set multiple times.

public List<String>
getVary()

Return the request header names subject to content negotiation.

public int
hashCode()

Overrides java.lang.Object.hashCode.

Implements java.util.Map.hashCode.

Returns the hash code value for this map.

public boolean
isEmpty()

Implements java.util.Map.isEmpty.

Returns true if this map contains no key-value mappings.

public Set<String>
keySet()

Implements java.util.Map.keySet.

Returns a Set view of the keys contained in this map.

public List<String>
put(String
key with which the specified value is to be associated
key
,
List<String>
value to be associated with the specified key
value
)

Implements java.util.Map.put.

Associates the specified value with the specified key in this map (optional operation).

public void
putAll(Map<? extends String, ? extends List<String>>
mappings to be stored in this map
map
)

Implements java.util.Map.putAll.

Copies all of the mappings from the specified map to this map (optional operation).

public List<String>
putIfAbsent(String
key with which the specified value is to be associated
key
,
List<String>
value to be associated with the specified key
value
)

Overrides default java.util.Map.putIfAbsent.

If the specified key is not already associated with a value (or is mapped to null) associates it with the given value and returns null, else returns the current value (optional operation).

public static HttpHeaders

Returns:

a read-only variant of the headers, or the original headers as-is (in case it happens to be a read-only HttpHeaders instance already)
readOnlyHttpHeaders
(MultiValueMap<String, String>
the headers to expose
headers
)

Apply a read-only HttpHeaders wrapper around the given headers, if necessary.

public static HttpHeaders

Returns:

a read-only variant of the headers, or the original headers as-is
readOnlyHttpHeaders
(HttpHeaders
the headers to expose
headers
)

Apply a read-only HttpHeaders wrapper around the given headers, if necessary.

public List<String>
remove(Object
key whose mapping is to be removed from the map
key
)

Implements java.util.Map.remove.

Removes the mapping for a key from this map if it is present (optional operation).

public void
set(String
the header name
headerName
,
String
the header value
headerValue
)

Implements org.springframework.util.MultiValueMap.set.

Set the given, single header value under the given name.

public void
setAccept(List<MediaType> acceptableMediaTypes)

Set the list of acceptable media types, as specified by the Accept header.

public void
setAcceptCharset(List<Charset> acceptableCharsets)

Set the list of acceptable charsets, as specified by the Accept-Charset header.

public void
setAcceptLanguage(List<Locale.LanguageRange> languages)

Set the acceptable language ranges, as specified by the Accept-Language header.

public void
public void
setAcceptPatch(List<MediaType> mediaTypes)

Set the list of acceptable media types for PATCH methods, as specified by the Accept-Patch header.

public void
setAccessControlAllowCredentials(boolean allowCredentials)

Set the (new) value of the Access-Control-Allow-Credentials response header.

public void
setAccessControlAllowHeaders(List<String> allowedHeaders)

Set the (new) value of the Access-Control-Allow-Headers response header.

public void
setAccessControlAllowMethods(List<HttpMethod> allowedMethods)

Set the (new) value of the Access-Control-Allow-Methods response header.

public void
setAccessControlAllowOrigin(String allowedOrigin)

Set the (new) value of the Access-Control-Allow-Origin response header.

public void
setAccessControlExposeHeaders(List<String> exposedHeaders)

Set the (new) value of the Access-Control-Expose-Headers response header.

public void
setAccessControlMaxAge(Duration maxAge)

Set the (new) value of the Access-Control-Max-Age response header.

public void
setAccessControlMaxAge(long maxAge)

Set the (new) value of the Access-Control-Max-Age response header.

public void
setAccessControlRequestHeaders(List<String> requestHeaders)

Set the (new) value of the Access-Control-Request-Headers request header.

public void
setAccessControlRequestMethod(HttpMethod requestMethod)

Set the (new) value of the Access-Control-Request-Method request header.

public void
setAll(Map<String, String>
the values.
values
)

Implements org.springframework.util.MultiValueMap.setAll.

Set the given values under.

public void
setAllow(Set<HttpMethod> allowedMethods)

Set the set of allowed HTTP methods, as specified by the Allow header.

public void
setBasicAuth(String
the username
username
,
String
the password
password
)

Set the value of the Authorization header to Basic Authentication based on the given username and password.

public void
setBasicAuth(String
the username
username
,
String
the password
password
,
Charset
the charset to use to convert the credentials into an octet sequence. Defaults to ISO-8859-1.
charset
)

Set the value of the Authorization header to Basic Authentication based on the given username and password.

public void
setBasicAuth(String
the encoded credentials
encodedCredentials
)

Set the value of the Authorization header to Basic Authentication based on the given encoded credentials.

public void
setBearerAuth(String
the Base64 encoded token
token
)

Set the value of the Authorization header to the given Bearer token.

public void
setCacheControl(CacheControl cacheControl)

Set a configured CacheControl instance as the new value of the Cache-Control header.

public void
setCacheControl(String cacheControl)

Set the (new) value of the Cache-Control header.

public void
setConnection(String connection)

Set the (new) value of the Connection header.

public void
setConnection(List<String> connection)

Set the (new) value of the Connection header.

public void
setContentDisposition(ContentDisposition contentDisposition)

Set the Content-Disposition header.

public void
setContentDispositionFormData(String
the control name
name
,
String
the filename (may be null)
filename
)

Set the Content-Disposition header when creating a "multipart/form-data" request.

public void
setContentLanguage(Locale locale)

Set the Locale of the content language, as specified by the Content-Language header.

public void
setContentLength(long contentLength)

Set the length of the body in bytes, as specified by the Content-Length header.

public void
setContentType(MediaType mediaType)

Set the media type of the body, as specified by the Content-Type header.

public void
setDate(ZonedDateTime date)

Set the date and time at which the message was created, as specified by the Date header.

public void
setDate(Instant date)

Set the date and time at which the message was created, as specified by the Date header.

public void
setDate(long date)

Set the date and time at which the message was created, as specified by the Date header.

public void
setDate(String headerName, long date)

Set the given date under the given header name after formatting it as a string using the RFC-1123 date-time formatter.

public void
setETag(String etag)

Set the (new) entity tag of the body, as specified by the ETag header.

public void
setExpires(ZonedDateTime expires)

Set the duration after which the message is no longer valid, as specified by the Expires header.

public void
setExpires(Instant expires)

Set the date and time at which the message is no longer valid, as specified by the Expires header.

public void
setExpires(long expires)

Set the date and time at which the message is no longer valid, as specified by the Expires header.

public void
setHost(InetSocketAddress host)

Set the (new) value of the Host header.

public void
setIfMatch(String ifMatch)

Set the (new) value of the If-Match header.

public void
setIfMatch(List<String> ifMatchList)

Set the (new) value of the If-Match header.

public void
setIfModifiedSince(ZonedDateTime ifModifiedSince)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setIfModifiedSince(Instant ifModifiedSince)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setIfModifiedSince(long ifModifiedSince)

Set the (new) value of the If-Modified-Since header.

public void
setIfNoneMatch(String ifNoneMatch)

Set the (new) value of the If-None-Match header.

public void
setIfNoneMatch(List<String> ifNoneMatchList)

Set the (new) values of the If-None-Match header.

public void
setIfUnmodifiedSince(ZonedDateTime ifUnmodifiedSince)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setIfUnmodifiedSince(Instant ifUnmodifiedSince)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setIfUnmodifiedSince(long ifUnmodifiedSince)

Set the (new) value of the If-Unmodified-Since header.

public void
setInstant(String headerName, Instant date)

Set the given date under the given header name after formatting it as a string using the RFC-1123 date-time formatter.

public void
setLastModified(ZonedDateTime lastModified)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setLastModified(Instant lastModified)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setLastModified(long lastModified)

Set the time the resource was last changed, as specified by the Last-Modified header.

public void
setLocation(URI location)

Set the (new) location of a resource, as specified by the Location header.

public void
setOrigin(String origin)

Set the (new) value of the Origin header.

private void
setOrRemove(String
the header name
headerName
,
String
the header value, or null for none
headerValue
)

Set the given header value, or remove the header if null.

public void
setPragma(String pragma)

Set the (new) value of the Pragma header.

public void
setRange(List<HttpRange> ranges)

Sets the (new) value of the Range header.

public void
setUpgrade(String upgrade)

Set the (new) value of the Upgrade header.

public void
setVary(List<String>
the request header names
requestHeaders
)

Set the request header names (e.g. "Accept-Language") for which the response is subject to content negotiation and variances based on the value of those request headers.

public void
setZonedDateTime(String headerName, ZonedDateTime date)

Set the given date under the given header name after formatting it as a string using the RFC-1123 date-time formatter.

public int
size()

Implements java.util.Map.size.

Returns the number of key-value mappings in this map.

protected String

Returns:

a combined result with comma delimitation
toCommaDelimitedString
(List<String>
the list of header values
headerValues
)

Turn the given list of header values into a comma-delimited result.

private static List<String>
public Map<String, String>
toSingleValueMap()

Implements org.springframework.util.MultiValueMap.toSingleValueMap.

Return a Map with the first values contained in this MultiValueMap.

public String
toString()

Overrides java.lang.Object.toString.

Returns a string representation of the object.

private static MultiValueMap<String, String>
public Collection<List<String>>
values()

Implements java.util.Map.values.

Returns a Collection view of the values contained in this map.

public static HttpHeaders

Returns:

a writable variant of the headers, or the original headers as-is
writableHttpHeaders
(HttpHeaders
the headers to expose
headers
)

Remove any read-only wrapper that may have been previously applied around the given headers via readOnlyHttpHeaders(HttpHeaders).

Inherited from java.lang.Object:
clonefinalizegetClassnotifynotifyAllwaitwaitwait