001/*
002 * Copyright 2002-2019 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.servlet.function;
018
019import java.net.URI;
020import java.time.Instant;
021import java.time.ZonedDateTime;
022import java.util.Set;
023import java.util.function.Consumer;
024
025import javax.servlet.http.Cookie;
026
027import org.springframework.core.ParameterizedTypeReference;
028import org.springframework.http.CacheControl;
029import org.springframework.http.HttpHeaders;
030import org.springframework.http.HttpMethod;
031import org.springframework.http.HttpStatus;
032import org.springframework.http.MediaType;
033import org.springframework.util.MultiValueMap;
034
035/**
036 * Entity-specific subtype of {@link ServerResponse} that exposes entity data.
037 *
038 * @author Arjen Poutsma
039 * @since 5.2
040 * @param <T> the entity type
041 */
042public interface EntityResponse<T> extends ServerResponse {
043
044        /**
045         * Return the entity that makes up this response.
046         */
047        T entity();
048
049
050        // Static builder methods
051
052        /**
053         * Create a builder with the given object.
054         * @param t the object that represents the body of the response
055         * @param <T> the type of element contained in the publisher
056         * @return the created builder
057         */
058        static <T> Builder<T> fromObject(T t) {
059                return DefaultEntityResponseBuilder.fromObject(t);
060        }
061
062        /**
063         * Create a builder with the given object and type reference.
064         * @param t the object that represents the body of the response
065         * @param entityType the type of the entity, used to capture the generic type
066         * @param <T> the type of element contained in the publisher
067         * @return the created builder
068         */
069        static <T> Builder<T> fromObject(T t, ParameterizedTypeReference<T> entityType) {
070                return DefaultEntityResponseBuilder.fromObject(t, entityType);
071        }
072
073
074        /**
075         * Defines a builder for {@code EntityResponse}.
076         * @param <T> the entity type
077         */
078        interface Builder<T> {
079
080                /**
081                 * Add the given header value(s) under the given name.
082                 * @param headerName   the header name
083                 * @param headerValues the header value(s)
084                 * @return this builder
085                 * @see HttpHeaders#add(String, String)
086                 */
087                Builder<T> header(String headerName, String... headerValues);
088
089                /**
090                 * Manipulate this response's headers with the given consumer. The
091                 * headers provided to the consumer are "live", so that the consumer can be used to
092                 * {@linkplain HttpHeaders#set(String, String) overwrite} existing header values,
093                 * {@linkplain HttpHeaders#remove(Object) remove} values, or use any of the other
094                 * {@link HttpHeaders} methods.
095                 * @param headersConsumer a function that consumes the {@code HttpHeaders}
096                 * @return this builder
097                 */
098                Builder<T> headers(Consumer<HttpHeaders> headersConsumer);
099
100                /**
101                 * Set the HTTP status.
102                 * @param status the response status
103                 * @return this builder
104                 */
105                Builder<T> status(HttpStatus status);
106
107                /**
108                 * Set the HTTP status.
109                 * @param status the response status
110                 * @return this builder
111                 */
112                Builder<T> status(int status);
113
114                /**
115                 * Add the given cookie to the response.
116                 * @param cookie the cookie to add
117                 * @return this builder
118                 */
119                Builder<T> cookie(Cookie cookie);
120
121                /**
122                 * Manipulate this response's cookies with the given consumer. The
123                 * cookies provided to the consumer are "live", so that the consumer can be used to
124                 * {@linkplain MultiValueMap#set(Object, Object) overwrite} existing cookies,
125                 * {@linkplain MultiValueMap#remove(Object) remove} cookies, or use any of the other
126                 * {@link MultiValueMap} methods.
127                 * @param cookiesConsumer a function that consumes the cookies
128                 * @return this builder
129                 */
130                Builder<T> cookies(Consumer<MultiValueMap<String, Cookie>> cookiesConsumer);
131
132                /**
133                 * Set the set of allowed {@link HttpMethod HTTP methods}, as specified
134                 * by the {@code Allow} header.
135                 * @param allowedMethods the allowed methods
136                 * @return this builder
137                 * @see HttpHeaders#setAllow(Set)
138                 */
139                Builder<T> allow(HttpMethod... allowedMethods);
140
141                /**
142                 * Set the set of allowed {@link HttpMethod HTTP methods}, as specified
143                 * by the {@code Allow} header.
144                 * @param allowedMethods the allowed methods
145                 * @return this builder
146                 * @see HttpHeaders#setAllow(Set)
147                 */
148                Builder<T> allow(Set<HttpMethod> allowedMethods);
149
150                /**
151                 * Set the entity tag of the body, as specified by the {@code ETag} header.
152                 * @param etag the new entity tag
153                 * @return this builder
154                 * @see HttpHeaders#setETag(String)
155                 */
156                Builder<T> eTag(String etag);
157
158                /**
159                 * Set the time the resource was last changed, as specified by the
160                 * {@code Last-Modified} header.
161                 * <p>The date should be specified as the number of milliseconds since
162                 * January 1, 1970 GMT.
163                 * @param lastModified the last modified date
164                 * @return this builder
165                 * @see HttpHeaders#setLastModified(long)
166                 */
167                Builder<T> lastModified(ZonedDateTime lastModified);
168
169                /**
170                 * Set the time the resource was last changed, as specified by the
171                 * {@code Last-Modified} header.
172                 * <p>The date should be specified as the number of milliseconds since
173                 * January 1, 1970 GMT.
174                 * @param lastModified the last modified date
175                 * @return this builder
176                 * @since 5.1.4
177                 * @see HttpHeaders#setLastModified(long)
178                 */
179                Builder<T> lastModified(Instant lastModified);
180                /**
181                 * Set the location of a resource, as specified by the {@code Location} header.
182                 * @param location the location
183                 * @return this builder
184                 * @see HttpHeaders#setLocation(URI)
185                 */
186                Builder<T> location(URI location);
187
188                /**
189                 * Set the caching directives for the resource, as specified by the HTTP 1.1
190                 * {@code Cache-Control} header.
191                 * <p>A {@code CacheControl} instance can be built like
192                 * {@code CacheControl.maxAge(3600).cachePublic().noTransform()}.
193                 * @param cacheControl a builder for cache-related HTTP response headers
194                 * @return this builder
195                 * @see <a href="https://tools.ietf.org/html/rfc7234#section-5.2">RFC-7234 Section 5.2</a>
196                 */
197                Builder<T> cacheControl(CacheControl cacheControl);
198
199                /**
200                 * Configure one or more request header names (e.g. "Accept-Language") to
201                 * add to the "Vary" response header to inform clients that the response is
202                 * subject to content negotiation and variances based on the value of the
203                 * given request headers. The configured request header names are added only
204                 * if not already present in the response "Vary" header.
205                 * @param requestHeaders request header names
206                 * @return this builder
207                 */
208                Builder<T> varyBy(String... requestHeaders);
209
210                /**
211                 * Set the length of the body in bytes, as specified by the
212                 * {@code Content-Length} header.
213                 * @param contentLength the content length
214                 * @return this builder
215                 * @see HttpHeaders#setContentLength(long)
216                 */
217                Builder<T> contentLength(long contentLength);
218
219                /**
220                 * Set the {@linkplain MediaType media type} of the body, as specified by the
221                 * {@code Content-Type} header.
222                 * @param contentType the content type
223                 * @return this builder
224                 * @see HttpHeaders#setContentType(MediaType)
225                 */
226                Builder<T> contentType(MediaType contentType);
227
228                /**
229                 * Build the response.
230                 * @return the built response
231                 */
232                EntityResponse<T> build();
233        }
234
235}