/*
 * Copyright 2002-2020 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
 *
 *      https://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.lang.reflect.Type;
import java.net.URI;
import java.nio.charset.Charset;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.Map;
import java.util.function.Consumer;

import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;

Extension of HttpEntity that also exposes the HTTP method and the target URL. For use in the RestTemplate to prepare requests with and in @Controller methods to represent request input.

Example use with the RestTemplate:

MyRequest body = ...
RequestEntity<MyRequest> request = RequestEntity
    .post("https://example.com/{foo}", "bar")
    .accept(MediaType.APPLICATION_JSON)
    .body(body);
ResponseEntity<MyResponse> response = template.exchange(request, MyResponse.class);

Example use in an @Controller:

@RequestMapping("/handle")
public void handle(RequestEntity<String> request) {
  HttpMethod method = request.getMethod();
  URI url = request.getUrl();
  String body = request.getBody();
}
Author:Arjen Poutsma, Sebastien Deleuze, Parviz Rozikov
Type parameters:
  • <T> – the body type
See Also:
Since:4.1
/** * Extension of {@link HttpEntity} that also exposes the HTTP method and the * target URL. For use in the {@code RestTemplate} to prepare requests with * and in {@code @Controller} methods to represent request input. * * <p>Example use with the {@code RestTemplate}: * <pre class="code"> * MyRequest body = ... * RequestEntity&lt;MyRequest&gt; request = RequestEntity * .post(&quot;https://example.com/{foo}&quot;, &quot;bar&quot;) * .accept(MediaType.APPLICATION_JSON) * .body(body); * ResponseEntity&lt;MyResponse&gt; response = template.exchange(request, MyResponse.class); * </pre> * * <p>Example use in an {@code @Controller}: * <pre class="code"> * &#64;RequestMapping("/handle") * public void handle(RequestEntity&lt;String&gt; request) { * HttpMethod method = request.getMethod(); * URI url = request.getUrl(); * String body = request.getBody(); * } * </pre> * * @author Arjen Poutsma * @author Sebastien Deleuze * @author Parviz Rozikov * @since 4.1 * @param <T> the body type * @see #getMethod() * @see #getUrl() * @see org.springframework.web.client.RestOperations#exchange(RequestEntity, Class) * @see ResponseEntity */
public class RequestEntity<T> extends HttpEntity<T> { @Nullable private final HttpMethod method; @Nullable private final URI url; @Nullable private final Type type;
Constructor with method and URL but without body nor headers.
Params:
  • method – the method
  • url – the URL
/** * Constructor with method and URL but without body nor headers. * @param method the method * @param url the URL */
public RequestEntity(HttpMethod method, URI url) { this(null, null, method, url, null); }
Constructor with method, URL and body but without headers.
Params:
  • body – the body
  • method – the method
  • url – the URL
/** * Constructor with method, URL and body but without headers. * @param body the body * @param method the method * @param url the URL */
public RequestEntity(@Nullable T body, HttpMethod method, URI url) { this(body, null, method, url, null); }
Constructor with method, URL, body and type but without headers.
Params:
  • body – the body
  • method – the method
  • url – the URL
  • type – the type used for generic type resolution
Since:4.3
/** * Constructor with method, URL, body and type but without headers. * @param body the body * @param method the method * @param url the URL * @param type the type used for generic type resolution * @since 4.3 */
public RequestEntity(@Nullable T body, HttpMethod method, URI url, Type type) { this(body, null, method, url, type); }
Constructor with method, URL and headers but without body.
Params:
  • headers – the headers
  • method – the method
  • url – the URL
/** * Constructor with method, URL and headers but without body. * @param headers the headers * @param method the method * @param url the URL */
public RequestEntity(MultiValueMap<String, String> headers, HttpMethod method, URI url) { this(null, headers, method, url, null); }
Constructor with method, URL, headers and body.
Params:
  • body – the body
  • headers – the headers
  • method – the method
  • url – the URL
/** * Constructor with method, URL, headers and body. * @param body the body * @param headers the headers * @param method the method * @param url the URL */
public RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, @Nullable HttpMethod method, URI url) { this(body, headers, method, url, null); }
Constructor with method, URL, headers, body and type.
Params:
  • body – the body
  • headers – the headers
  • method – the method
  • url – the URL
  • type – the type used for generic type resolution
Since:4.3
/** * Constructor with method, URL, headers, body and type. * @param body the body * @param headers the headers * @param method the method * @param url the URL * @param type the type used for generic type resolution * @since 4.3 */
public RequestEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, @Nullable HttpMethod method, @Nullable URI url, @Nullable Type type) { super(body, headers); this.method = method; this.url = url; this.type = type; }
Return the HTTP method of the request.
Returns:the HTTP method as an HttpMethod enum value
/** * Return the HTTP method of the request. * @return the HTTP method as an {@code HttpMethod} enum value */
@Nullable public HttpMethod getMethod() { return this.method; }
Return the URL of the request.
/** * Return the URL of the request. */
public URI getUrl() { if (this.url == null) { throw new UnsupportedOperationException(); } return this.url; }
Return the type of the request's body.
Returns:the request's body type, or null if not known
Since:4.3
/** * Return the type of the request's body. * @return the request's body type, or {@code null} if not known * @since 4.3 */
@Nullable public Type getType() { if (this.type == null) { T body = getBody(); if (body != null) { return body.getClass(); } } return this.type; } @Override public boolean equals(@Nullable Object other) { if (this == other) { return true; } if (!super.equals(other)) { return false; } RequestEntity<?> otherEntity = (RequestEntity<?>) other; return (ObjectUtils.nullSafeEquals(getMethod(), otherEntity.getMethod()) && ObjectUtils.nullSafeEquals(getUrl(), otherEntity.getUrl())); } @Override public int hashCode() { int hashCode = super.hashCode(); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(this.method); hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getUrl()); return hashCode; } @Override public String toString() { return format(getMethod(), getUrl().toString(), getBody(), getHeaders()); } static <T> String format(@Nullable HttpMethod httpMethod, String url, @Nullable T body, HttpHeaders headers) { StringBuilder builder = new StringBuilder("<"); builder.append(httpMethod); builder.append(' '); builder.append(url); builder.append(','); if (body != null) { builder.append(body); builder.append(','); } builder.append(headers); builder.append('>'); return builder.toString(); } // Static builder methods
Create a builder with the given method and url.
Params:
  • method – the HTTP method (GET, POST, etc)
  • url – the URL
Returns:the created builder
/** * Create a builder with the given method and url. * @param method the HTTP method (GET, POST, etc) * @param url the URL * @return the created builder */
public static BodyBuilder method(HttpMethod method, URI url) { return new DefaultBodyBuilder(method, url); }
Create a builder with the given HTTP method, URI template, and variables.
Params:
  • method – the HTTP method (GET, POST, etc)
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create a builder with the given HTTP method, URI template, and variables. * @param method the HTTP method (GET, POST, etc) * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static BodyBuilder method(HttpMethod method, String uriTemplate, Object... uriVariables) { return new DefaultBodyBuilder(method, uriTemplate, uriVariables); }
Create a builder with the given HTTP method, URI template, and variables.
Params:
  • method – the HTTP method (GET, POST, etc)
  • uriTemplate – the uri template to use
Returns:the created builder
Since:5.3
/** * Create a builder with the given HTTP method, URI template, and variables. * @param method the HTTP method (GET, POST, etc) * @param uriTemplate the uri template to use * @return the created builder * @since 5.3 */
public static BodyBuilder method(HttpMethod method, String uriTemplate, Map<String, ?> uriVariables) { return new DefaultBodyBuilder(method, uriTemplate, uriVariables); }
Create an HTTP GET builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Create an HTTP GET builder with the given url. * @param url the URL * @return the created builder */
public static HeadersBuilder<?> get(URI url) { return method(HttpMethod.GET, url); }
Create an HTTP GET builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create an HTTP GET builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static HeadersBuilder<?> get(String uriTemplate, Object... uriVariables) { return method(HttpMethod.GET, uriTemplate, uriVariables); }
Create an HTTP HEAD builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Create an HTTP HEAD builder with the given url. * @param url the URL * @return the created builder */
public static HeadersBuilder<?> head(URI url) { return method(HttpMethod.HEAD, url); }
Create an HTTP HEAD builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create an HTTP HEAD builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static HeadersBuilder<?> head(String uriTemplate, Object... uriVariables) { return method(HttpMethod.HEAD, uriTemplate, uriVariables); }
Create an HTTP POST builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Create an HTTP POST builder with the given url. * @param url the URL * @return the created builder */
public static BodyBuilder post(URI url) { return method(HttpMethod.POST, url); }
Create an HTTP POST builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create an HTTP POST builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static BodyBuilder post(String uriTemplate, Object... uriVariables) { return method(HttpMethod.POST, uriTemplate, uriVariables); }
Create an HTTP PUT builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Create an HTTP PUT builder with the given url. * @param url the URL * @return the created builder */
public static BodyBuilder put(URI url) { return method(HttpMethod.PUT, url); }
Create an HTTP PUT builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create an HTTP PUT builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static BodyBuilder put(String uriTemplate, Object... uriVariables) { return method(HttpMethod.PUT, uriTemplate, uriVariables); }
Create an HTTP PATCH builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Create an HTTP PATCH builder with the given url. * @param url the URL * @return the created builder */
public static BodyBuilder patch(URI url) { return method(HttpMethod.PATCH, url); }
Create an HTTP PATCH builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create an HTTP PATCH builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static BodyBuilder patch(String uriTemplate, Object... uriVariables) { return method(HttpMethod.PATCH, uriTemplate, uriVariables); }
Create an HTTP DELETE builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Create an HTTP DELETE builder with the given url. * @param url the URL * @return the created builder */
public static HeadersBuilder<?> delete(URI url) { return method(HttpMethod.DELETE, url); }
Create an HTTP DELETE builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Create an HTTP DELETE builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static HeadersBuilder<?> delete(String uriTemplate, Object... uriVariables) { return method(HttpMethod.DELETE, uriTemplate, uriVariables); }
Creates an HTTP OPTIONS builder with the given url.
Params:
  • url – the URL
Returns:the created builder
/** * Creates an HTTP OPTIONS builder with the given url. * @param url the URL * @return the created builder */
public static HeadersBuilder<?> options(URI url) { return method(HttpMethod.OPTIONS, url); }
Creates an HTTP OPTIONS builder with the given string base uri template.
Params:
  • uriTemplate – the uri template to use
  • uriVariables – variables to expand the URI template with
Returns:the created builder
Since:5.3
/** * Creates an HTTP OPTIONS builder with the given string base uri template. * @param uriTemplate the uri template to use * @param uriVariables variables to expand the URI template with * @return the created builder * @since 5.3 */
public static HeadersBuilder<?> options(String uriTemplate, Object... uriVariables) { return method(HttpMethod.OPTIONS, uriTemplate, uriVariables); }
Defines a builder that adds headers to the request entity.
Type parameters:
  • <B> – the builder subclass
/** * Defines a builder that adds headers to the request entity. * @param <B> the builder subclass */
public interface HeadersBuilder<B extends HeadersBuilder<B>> {
Add the given, single header value under the given name.
Params:
  • headerName – the header name
  • headerValues – the header value(s)
See Also:
Returns:this builder
/** * Add the given, single header value under the given name. * @param headerName the header name * @param headerValues the header value(s) * @return this builder * @see HttpHeaders#add(String, String) */
B header(String headerName, String... headerValues);
Copy the given headers into the entity's headers map.
Params:
  • headers – the existing HttpHeaders to copy from
See Also:
Returns:this builder
Since:5.2
/** * Copy the given headers into the entity's headers map. * @param headers the existing HttpHeaders to copy from * @return this builder * @since 5.2 * @see HttpHeaders#add(String, String) */
B headers(@Nullable HttpHeaders headers);
Manipulate this entity's headers with the given consumer. The headers provided to the consumer are "live", so that the consumer can be used to overwrite existing header values, remove values, or use any of the other HttpHeaders methods.
Params:
  • headersConsumer – a function that consumes the HttpHeaders
Returns:this builder
Since:5.2
/** * Manipulate this entity's headers with the given consumer. The * headers provided to the consumer are "live", so that the consumer can be used to * {@linkplain HttpHeaders#set(String, String) overwrite} existing header values, * {@linkplain HttpHeaders#remove(Object) remove} values, or use any of the other * {@link HttpHeaders} methods. * @param headersConsumer a function that consumes the {@code HttpHeaders} * @return this builder * @since 5.2 */
B headers(Consumer<HttpHeaders> headersConsumer);
Set the list of acceptable media types, as specified by the Accept header.
Params:
  • acceptableMediaTypes – the acceptable media types
/** * Set the list of acceptable {@linkplain MediaType media types}, as * specified by the {@code Accept} header. * @param acceptableMediaTypes the acceptable media types */
B accept(MediaType... acceptableMediaTypes);
Set the list of acceptable charsets, as specified by the Accept-Charset header.
Params:
  • acceptableCharsets – the acceptable charsets
/** * Set the list of acceptable {@linkplain Charset charsets}, as specified * by the {@code Accept-Charset} header. * @param acceptableCharsets the acceptable charsets */
B acceptCharset(Charset... acceptableCharsets);
Set the value of the If-Modified-Since header.
Params:
  • ifModifiedSince – the new value of the header
Since:5.1.4
/** * Set the value of the {@code If-Modified-Since} header. * @param ifModifiedSince the new value of the header * @since 5.1.4 */
B ifModifiedSince(ZonedDateTime ifModifiedSince);
Set the value of the If-Modified-Since header.
Params:
  • ifModifiedSince – the new value of the header
Since:5.1.4
/** * Set the value of the {@code If-Modified-Since} header. * @param ifModifiedSince the new value of the header * @since 5.1.4 */
B ifModifiedSince(Instant ifModifiedSince);
Set the value of the If-Modified-Since header.

The date should be specified as the number of milliseconds since January 1, 1970 GMT.

Params:
  • ifModifiedSince – the new value of the header
/** * Set the value of the {@code If-Modified-Since} header. * <p>The date should be specified as the number of milliseconds since * January 1, 1970 GMT. * @param ifModifiedSince the new value of the header */
B ifModifiedSince(long ifModifiedSince);
Set the values of the If-None-Match header.
Params:
  • ifNoneMatches – the new value of the header
/** * Set the values of the {@code If-None-Match} header. * @param ifNoneMatches the new value of the header */
B ifNoneMatch(String... ifNoneMatches);
Builds the request entity with no body.
See Also:
Returns:the request entity
/** * Builds the request entity with no body. * @return the request entity * @see BodyBuilder#body(Object) */
RequestEntity<Void> build(); }
Defines a builder that adds a body to the response entity.
/** * Defines a builder that adds a body to the response entity. */
public interface BodyBuilder extends HeadersBuilder<BodyBuilder> {
Set the length of the body in bytes, as specified by the Content-Length header.
Params:
  • contentLength – the content length
See Also:
Returns:this builder
/** * Set the length of the body in bytes, as specified by the * {@code Content-Length} header. * @param contentLength the content length * @return this builder * @see HttpHeaders#setContentLength(long) */
BodyBuilder contentLength(long contentLength);
Set the media type of the body, as specified by the Content-Type header.
Params:
  • contentType – the content type
See Also:
Returns:this builder
/** * Set the {@linkplain MediaType media type} of the body, as specified * by the {@code Content-Type} header. * @param contentType the content type * @return this builder * @see HttpHeaders#setContentType(MediaType) */
BodyBuilder contentType(MediaType contentType);
Set the body of the request entity and build the RequestEntity.
Params:
  • body – the body of the request entity
Type parameters:
  • <T> – the type of the body
Returns:the built request entity
/** * Set the body of the request entity and build the RequestEntity. * @param <T> the type of the body * @param body the body of the request entity * @return the built request entity */
<T> RequestEntity<T> body(T body);
Set the body and type of the request entity and build the RequestEntity.
Params:
  • body – the body of the request entity
  • type – the type of the body, useful for generic type resolution
Type parameters:
  • <T> – the type of the body
Returns:the built request entity
Since:4.3
/** * Set the body and type of the request entity and build the RequestEntity. * @param <T> the type of the body * @param body the body of the request entity * @param type the type of the body, useful for generic type resolution * @return the built request entity * @since 4.3 */
<T> RequestEntity<T> body(T body, Type type); } private static class DefaultBodyBuilder implements BodyBuilder { private final HttpMethod method; private final HttpHeaders headers = new HttpHeaders(); @Nullable private final URI uri; @Nullable String uriTemplate; @Nullable private Object[] uriVarsArray; @Nullable Map<String, ?> uriVarsMap; DefaultBodyBuilder(HttpMethod method, URI url) { this.method = method; this.uri = url; this.uriTemplate = null; this.uriVarsArray = null; this.uriVarsMap = null; } DefaultBodyBuilder(HttpMethod method, String uriTemplate, Object... uriVars) { this.method = method; this.uri = null; this.uriTemplate = uriTemplate; this.uriVarsArray = uriVars; this.uriVarsMap = null; } DefaultBodyBuilder(HttpMethod method, String uriTemplate, Map<String, ?> uriVars) { this.method = method; this.uri = null; this.uriTemplate = uriTemplate; this.uriVarsArray = null; this.uriVarsMap = uriVars; } @Override public BodyBuilder header(String headerName, String... headerValues) { for (String headerValue : headerValues) { this.headers.add(headerName, headerValue); } return this; } @Override public BodyBuilder headers(@Nullable HttpHeaders headers) { if (headers != null) { this.headers.putAll(headers); } return this; } @Override public BodyBuilder headers(Consumer<HttpHeaders> headersConsumer) { headersConsumer.accept(this.headers); return this; } @Override public BodyBuilder accept(MediaType... acceptableMediaTypes) { this.headers.setAccept(Arrays.asList(acceptableMediaTypes)); return this; } @Override public BodyBuilder acceptCharset(Charset... acceptableCharsets) { this.headers.setAcceptCharset(Arrays.asList(acceptableCharsets)); return this; } @Override public BodyBuilder contentLength(long contentLength) { this.headers.setContentLength(contentLength); return this; } @Override public BodyBuilder contentType(MediaType contentType) { this.headers.setContentType(contentType); return this; } @Override public BodyBuilder ifModifiedSince(ZonedDateTime ifModifiedSince) { this.headers.setIfModifiedSince(ifModifiedSince); return this; } @Override public BodyBuilder ifModifiedSince(Instant ifModifiedSince) { this.headers.setIfModifiedSince(ifModifiedSince); return this; } @Override public BodyBuilder ifModifiedSince(long ifModifiedSince) { this.headers.setIfModifiedSince(ifModifiedSince); return this; } @Override public BodyBuilder ifNoneMatch(String... ifNoneMatches) { this.headers.setIfNoneMatch(Arrays.asList(ifNoneMatches)); return this; } @Override public RequestEntity<Void> build() { return buildInternal(null, null); } @Override public <T> RequestEntity<T> body(T body) { return buildInternal(body, null); } @Override public <T> RequestEntity<T> body(T body, Type type) { return buildInternal(body, type); } private <T> RequestEntity<T> buildInternal(@Nullable T body, @Nullable Type type) { if (this.uri != null) { return new RequestEntity<>(body, this.headers, this.method, this.uri, type); } else if (this.uriTemplate != null){ return new UriTemplateRequestEntity<>(body, this.headers, this.method, type, this.uriTemplate, this.uriVarsArray, this.uriVarsMap); } else { throw new IllegalStateException("Neither URI nor URI template"); } } }
RequestEntity initialized with a URI template and variables instead of a URI.
Type parameters:
  • <T> – the body type
Since:5.3
/** * RequestEntity initialized with a URI template and variables instead of a {@link URI}. * @since 5.3 * @param <T> the body type */
public static class UriTemplateRequestEntity<T> extends RequestEntity<T> { private final String uriTemplate; @Nullable private final Object[] uriVarsArray; @Nullable private final Map<String, ?> uriVarsMap; UriTemplateRequestEntity( @Nullable T body, @Nullable MultiValueMap<String, String> headers, @Nullable HttpMethod method, @Nullable Type type, String uriTemplate, @Nullable Object[] uriVarsArray, @Nullable Map<String, ?> uriVarsMap) { super(body, headers, method, null, type); this.uriTemplate = uriTemplate; this.uriVarsArray = uriVarsArray; this.uriVarsMap = uriVarsMap; } public String getUriTemplate() { return this.uriTemplate; } @Nullable public Object[] getVars() { return this.uriVarsArray; } @Nullable public Map<String, ?> getVarsMap() { return this.uriVarsMap; } @Override public String toString() { return format(getMethod(), getUriTemplate(), getBody(), getHeaders()); } } }