|
|
|
@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
|
|
|
|
|
/* |
|
|
|
|
* Copyright 2002-2017 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. |
|
|
|
@ -39,6 +39,7 @@ import org.springframework.http.HttpStatus;
@@ -39,6 +39,7 @@ import org.springframework.http.HttpStatus;
|
|
|
|
|
import org.springframework.http.MediaType; |
|
|
|
|
import org.springframework.http.ResponseCookie; |
|
|
|
|
import org.springframework.http.codec.HttpMessageWriter; |
|
|
|
|
import org.springframework.http.server.reactive.AbstractServerHttpResponse; |
|
|
|
|
import org.springframework.http.server.reactive.ServerHttpRequest; |
|
|
|
|
import org.springframework.http.server.reactive.ServerHttpResponse; |
|
|
|
|
import org.springframework.util.Assert; |
|
|
|
@ -53,11 +54,12 @@ import org.springframework.web.server.ServerWebExchange;
@@ -53,11 +54,12 @@ import org.springframework.web.server.ServerWebExchange;
|
|
|
|
|
* Default {@link ServerResponse.BodyBuilder} implementation. |
|
|
|
|
* |
|
|
|
|
* @author Arjen Poutsma |
|
|
|
|
* @author Juergen Hoeller |
|
|
|
|
* @since 5.0 |
|
|
|
|
*/ |
|
|
|
|
class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder { |
|
|
|
|
|
|
|
|
|
private final HttpStatus statusCode; |
|
|
|
|
private final int statusCode; |
|
|
|
|
|
|
|
|
|
private final HttpHeaders headers = new HttpHeaders(); |
|
|
|
|
|
|
|
|
@ -66,7 +68,17 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -66,7 +68,17 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
private final Map<String, Object> hints = new HashMap<>(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public DefaultServerResponseBuilder(ServerResponse other) { |
|
|
|
|
this.statusCode = (other instanceof AbstractServerResponse ? |
|
|
|
|
((AbstractServerResponse) other).statusCode : other.statusCode().value()); |
|
|
|
|
this.headers.addAll(other.headers()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public DefaultServerResponseBuilder(HttpStatus statusCode) { |
|
|
|
|
this.statusCode = statusCode.value(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public DefaultServerResponseBuilder(int statusCode) { |
|
|
|
|
this.statusCode = statusCode; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -81,22 +93,21 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -81,22 +93,21 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public ServerResponse.BodyBuilder headers(Consumer<HttpHeaders> headersConsumer) { |
|
|
|
|
Assert.notNull(headersConsumer, "'headersConsumer' must not be null"); |
|
|
|
|
Assert.notNull(headersConsumer, "Consumer must not be null"); |
|
|
|
|
headersConsumer.accept(this.headers); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public ServerResponse.BodyBuilder cookie(ResponseCookie cookie) { |
|
|
|
|
Assert.notNull(cookie, "'cookie' must not be null"); |
|
|
|
|
Assert.notNull(cookie, "ResponseCookie must not be null"); |
|
|
|
|
this.cookies.add(cookie.getName(), cookie); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public ServerResponse.BodyBuilder cookies( |
|
|
|
|
Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) { |
|
|
|
|
Assert.notNull(cookiesConsumer, "'cookiesConsumer' must not be null"); |
|
|
|
|
public ServerResponse.BodyBuilder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) { |
|
|
|
|
Assert.notNull(cookiesConsumer, "Consumer must not be null"); |
|
|
|
|
cookiesConsumer.accept(this.cookies); |
|
|
|
|
return this; |
|
|
|
|
} |
|
|
|
@ -177,7 +188,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -177,7 +188,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Mono<ServerResponse> build(Publisher<Void> voidPublisher) { |
|
|
|
|
Assert.notNull(voidPublisher, "'voidPublisher' must not be null"); |
|
|
|
|
Assert.notNull(voidPublisher, "Publisher must not be null"); |
|
|
|
|
return build((exchange, handlerStrategies) -> |
|
|
|
|
Mono.from(voidPublisher).then(exchange.getResponse().setComplete())); |
|
|
|
|
} |
|
|
|
@ -186,15 +197,15 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -186,15 +197,15 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
public Mono<ServerResponse> build( |
|
|
|
|
BiFunction<ServerWebExchange, ServerResponse.Context, Mono<Void>> writeFunction) { |
|
|
|
|
|
|
|
|
|
Assert.notNull(writeFunction, "'writeFunction' must not be null"); |
|
|
|
|
return Mono.just(new WriterFunctionServerResponse(this.statusCode, this.headers, |
|
|
|
|
this.cookies, writeFunction)); |
|
|
|
|
Assert.notNull(writeFunction, "BiFunction must not be null"); |
|
|
|
|
return Mono.just( |
|
|
|
|
new WriterFunctionServerResponse(this.statusCode, this.headers, this.cookies, writeFunction)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public <T, P extends Publisher<T>> Mono<ServerResponse> body(P publisher, Class<T> elementClass) { |
|
|
|
|
Assert.notNull(publisher, "'publisher' must not be null"); |
|
|
|
|
Assert.notNull(elementClass, "'elementClass' must not be null"); |
|
|
|
|
Assert.notNull(publisher, "Publisher must not be null"); |
|
|
|
|
Assert.notNull(elementClass, "Element Class must not be null"); |
|
|
|
|
|
|
|
|
|
return new DefaultEntityResponseBuilder<>(publisher, |
|
|
|
|
BodyInserters.fromPublisher(publisher, elementClass)) |
|
|
|
@ -208,8 +219,8 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -208,8 +219,8 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
public <T, P extends Publisher<T>> Mono<ServerResponse> body(P publisher, |
|
|
|
|
ParameterizedTypeReference<T> typeReference) { |
|
|
|
|
|
|
|
|
|
Assert.notNull(publisher, "'publisher' must not be null"); |
|
|
|
|
Assert.notNull(typeReference, "'typeReference' must not be null"); |
|
|
|
|
Assert.notNull(publisher, "Publisher must not be null"); |
|
|
|
|
Assert.notNull(typeReference, "ParameterizedTypeReference must not be null"); |
|
|
|
|
|
|
|
|
|
return new DefaultEntityResponseBuilder<>(publisher, |
|
|
|
|
BodyInserters.fromPublisher(publisher, typeReference)) |
|
|
|
@ -221,9 +232,9 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -221,9 +232,9 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Mono<ServerResponse> syncBody(Object body) { |
|
|
|
|
Assert.notNull(body, "'body' must not be null"); |
|
|
|
|
Assert.isTrue(!(body instanceof Publisher), "Please specify the element class by using " + |
|
|
|
|
"body(Publisher, Class)"); |
|
|
|
|
Assert.notNull(body, "Body must not be null"); |
|
|
|
|
Assert.isTrue(!(body instanceof Publisher), |
|
|
|
|
"Please specify the element class by using body(Publisher, Class)"); |
|
|
|
|
|
|
|
|
|
return new DefaultEntityResponseBuilder<>(body, |
|
|
|
|
BodyInserters.fromObject(body)) |
|
|
|
@ -235,14 +246,14 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -235,14 +246,14 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Mono<ServerResponse> body(BodyInserter<?, ? super ServerHttpResponse> inserter) { |
|
|
|
|
Assert.notNull(inserter, "'inserter' must not be null"); |
|
|
|
|
return Mono.just(new BodyInserterServerResponse<>(this.statusCode, this.headers, |
|
|
|
|
this.cookies, inserter, this.hints)); |
|
|
|
|
Assert.notNull(inserter, "BodyInserter must not be null"); |
|
|
|
|
return Mono.just( |
|
|
|
|
new BodyInserterServerResponse<>(this.statusCode, this.headers, this.cookies, inserter, this.hints)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Mono<ServerResponse> render(String name, Object... modelAttributes) { |
|
|
|
|
Assert.hasLength(name, "'name' must not be empty"); |
|
|
|
|
Assert.hasLength(name, "Name must not be empty"); |
|
|
|
|
|
|
|
|
|
return new DefaultRenderingResponseBuilder(name) |
|
|
|
|
.headers(this.headers) |
|
|
|
@ -254,7 +265,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -254,7 +265,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public Mono<ServerResponse> render(String name, Map<String, ?> model) { |
|
|
|
|
Assert.hasLength(name, "'name' must not be empty"); |
|
|
|
|
Assert.hasLength(name, "Name must not be empty"); |
|
|
|
|
|
|
|
|
|
return new DefaultRenderingResponseBuilder(name) |
|
|
|
|
.headers(this.headers) |
|
|
|
@ -267,14 +278,15 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -267,14 +278,15 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
static abstract class AbstractServerResponse implements ServerResponse { |
|
|
|
|
|
|
|
|
|
private final HttpStatus statusCode; |
|
|
|
|
final int statusCode; |
|
|
|
|
|
|
|
|
|
private final HttpHeaders headers; |
|
|
|
|
|
|
|
|
|
private final MultiValueMap<String, ResponseCookie> cookies; |
|
|
|
|
|
|
|
|
|
protected AbstractServerResponse(HttpStatus statusCode, HttpHeaders headers, |
|
|
|
|
protected AbstractServerResponse(int statusCode, HttpHeaders headers, |
|
|
|
|
MultiValueMap<String, ResponseCookie> cookies) { |
|
|
|
|
|
|
|
|
|
this.statusCode = statusCode; |
|
|
|
|
this.headers = readOnlyCopy(headers); |
|
|
|
|
this.cookies = readOnlyCopy(cookies); |
|
|
|
@ -294,7 +306,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -294,7 +306,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public final HttpStatus statusCode() { |
|
|
|
|
return this.statusCode; |
|
|
|
|
return HttpStatus.valueOf(this.statusCode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@ -308,8 +320,17 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -308,8 +320,17 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
protected void writeStatusAndHeaders(ServerHttpResponse response) { |
|
|
|
|
response.setStatusCode(this.statusCode); |
|
|
|
|
|
|
|
|
|
if (response instanceof AbstractServerHttpResponse) { |
|
|
|
|
((AbstractServerHttpResponse) response).setStatusCodeValue(this.statusCode); |
|
|
|
|
} |
|
|
|
|
else { |
|
|
|
|
HttpStatus status = HttpStatus.resolve(this.statusCode); |
|
|
|
|
if (status == null) { |
|
|
|
|
throw new IllegalStateException( |
|
|
|
|
"Unresolvable HttpStatus for general ServerHttpResponse: " + this.statusCode); |
|
|
|
|
} |
|
|
|
|
response.setStatusCode(status); |
|
|
|
|
} |
|
|
|
|
copy(this.headers, response.getHeaders()); |
|
|
|
|
copy(this.cookies, response.getCookies()); |
|
|
|
|
} |
|
|
|
@ -328,7 +349,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -328,7 +349,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
private final BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction; |
|
|
|
|
|
|
|
|
|
public WriterFunctionServerResponse(HttpStatus statusCode, HttpHeaders headers, |
|
|
|
|
public WriterFunctionServerResponse(int statusCode, HttpHeaders headers, |
|
|
|
|
MultiValueMap<String, ResponseCookie> cookies, |
|
|
|
|
BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction) { |
|
|
|
|
|
|
|
|
@ -350,7 +371,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
@@ -350,7 +371,7 @@ class DefaultServerResponseBuilder implements ServerResponse.BodyBuilder {
|
|
|
|
|
|
|
|
|
|
private final Map<String, Object> hints; |
|
|
|
|
|
|
|
|
|
public BodyInserterServerResponse(HttpStatus statusCode, HttpHeaders headers, |
|
|
|
|
public BodyInserterServerResponse(int statusCode, HttpHeaders headers, |
|
|
|
|
MultiValueMap<String, ResponseCookie> cookies, |
|
|
|
|
BodyInserter<T, ? super ServerHttpResponse> inserter, Map<String, Object> hints) { |
|
|
|
|
|
|
|
|
|