Skip to content

Commit 9623cde

Browse files
committed
Functional response builders allow for non-standard HTTP status codes
Issue: SPR-16366
1 parent 91e39d5 commit 9623cde

File tree

7 files changed

+137
-81
lines changed

7 files changed

+137
-81
lines changed

spring-web/src/main/java/org/springframework/http/server/reactive/AbstractServerHttpResponse.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -43,6 +43,7 @@
4343
* Base class for {@link ServerHttpResponse} implementations.
4444
*
4545
* @author Rossen Stoyanchev
46+
* @author Juergen Hoeller
4647
* @author Sebastien Deleuze
4748
* @since 5.0
4849
*/
@@ -112,7 +113,7 @@ public HttpStatus getStatusCode() {
112113
* @param statusCode the HTTP status as an integer value
113114
* @since 5.0.1
114115
*/
115-
public void setStatusCodeValue(Integer statusCode) {
116+
public void setStatusCodeValue(@Nullable Integer statusCode) {
116117
this.statusCode = statusCode;
117118
}
118119

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultEntityResponseBuilder.java

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -50,6 +50,7 @@
5050
* Default {@link EntityResponse.Builder} implementation.
5151
*
5252
* @author Arjen Poutsma
53+
* @author Juergen Hoeller
5354
* @since 5.0
5455
*/
5556
class DefaultEntityResponseBuilder<T> implements EntityResponse.Builder<T> {
@@ -58,7 +59,7 @@ class DefaultEntityResponseBuilder<T> implements EntityResponse.Builder<T> {
5859

5960
private final BodyInserter<T, ? super ServerHttpResponse> inserter;
6061

61-
private HttpStatus status = HttpStatus.OK;
62+
private int status = HttpStatus.OK.value();
6263

6364
private final HttpHeaders headers = new HttpHeaders();
6465

@@ -75,22 +76,27 @@ public DefaultEntityResponseBuilder(T entity, BodyInserter<T, ? super ServerHttp
7576

7677
@Override
7778
public EntityResponse.Builder<T> status(HttpStatus status) {
78-
Assert.notNull(status, "'status' must not be null");
79+
Assert.notNull(status, "HttpStatus must not be null");
80+
this.status = status.value();
81+
return this;
82+
}
83+
84+
@Override
85+
public EntityResponse.Builder<T> status(int status) {
7986
this.status = status;
8087
return this;
8188
}
8289

8390
@Override
8491
public EntityResponse.Builder<T> cookie(ResponseCookie cookie) {
85-
Assert.notNull(cookie, "'cookie' must not be null");
92+
Assert.notNull(cookie, "ResponseCookie must not be null");
8693
this.cookies.add(cookie.getName(), cookie);
8794
return this;
8895
}
8996

9097
@Override
91-
public EntityResponse.Builder<T> cookies(
92-
Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
93-
Assert.notNull(cookiesConsumer, "'cookiesConsumer' must not be null");
98+
public EntityResponse.Builder<T> cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
99+
Assert.notNull(cookiesConsumer, "Consumer must not be null");
94100
cookiesConsumer.accept(this.cookies);
95101
return this;
96102
}
@@ -182,8 +188,8 @@ public EntityResponse.Builder<T> varyBy(String... requestHeaders) {
182188

183189
@Override
184190
public Mono<EntityResponse<T>> build() {
185-
return Mono.just(new DefaultEntityResponse<T>(this.status, this.headers, this.cookies,
186-
this.entity, this.inserter, this.hints));
191+
return Mono.just(new DefaultEntityResponse<T>(
192+
this.status, this.headers, this.cookies, this.entity, this.inserter, this.hints));
187193
}
188194

189195

@@ -197,8 +203,7 @@ private final static class DefaultEntityResponse<T>
197203

198204
private final Map<String, Object> hints;
199205

200-
201-
public DefaultEntityResponse(HttpStatus statusCode, HttpHeaders headers,
206+
public DefaultEntityResponse(int statusCode, HttpHeaders headers,
202207
MultiValueMap<String, ResponseCookie> cookies, T entity,
203208
BodyInserter<T, ? super ServerHttpResponse> inserter, Map<String, Object> hints) {
204209

@@ -208,7 +213,6 @@ public DefaultEntityResponse(HttpStatus statusCode, HttpHeaders headers,
208213
this.hints = hints;
209214
}
210215

211-
212216
@Override
213217
public T entity() {
214218
return this.entity;
@@ -228,12 +232,10 @@ public Mono<Void> writeTo(ServerWebExchange exchange, Context context) {
228232
public List<HttpMessageWriter<?>> messageWriters() {
229233
return context.messageWriters();
230234
}
231-
232235
@Override
233236
public Optional<ServerHttpRequest> serverRequest() {
234237
return Optional.of(exchange.getRequest());
235238
}
236-
237239
@Override
238240
public Map<String, Object> hints() {
239241
return hints;

spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultRenderingResponseBuilder.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -47,13 +47,14 @@
4747
* Default {@link RenderingResponse.Builder} implementation.
4848
*
4949
* @author Arjen Poutsma
50+
* @author Juergen Hoeller
5051
* @since 5.0
5152
*/
5253
class DefaultRenderingResponseBuilder implements RenderingResponse.Builder {
5354

5455
private final String name;
5556

56-
private HttpStatus status = HttpStatus.OK;
57+
private int status = HttpStatus.OK.value();
5758

5859
private final HttpHeaders headers = new HttpHeaders();
5960

@@ -62,35 +63,49 @@ class DefaultRenderingResponseBuilder implements RenderingResponse.Builder {
6263
private final Map<String, Object> model = new LinkedHashMap<>();
6364

6465

66+
public DefaultRenderingResponseBuilder(RenderingResponse other) {
67+
this.name = other.name();
68+
this.status = (other instanceof DefaultRenderingResponse ?
69+
((DefaultRenderingResponse) other).statusCode : other.statusCode().value());
70+
this.headers.putAll(other.headers());
71+
this.model.putAll(other.model());
72+
}
73+
6574
public DefaultRenderingResponseBuilder(String name) {
6675
this.name = name;
6776
}
6877

6978

7079
@Override
7180
public RenderingResponse.Builder status(HttpStatus status) {
72-
Assert.notNull(status, "'status' must not be null");
81+
Assert.notNull(status, "HttpStatus must not be null");
82+
this.status = status.value();
83+
return this;
84+
}
85+
86+
@Override
87+
public RenderingResponse.Builder status(int status) {
7388
this.status = status;
7489
return this;
7590
}
7691

7792
@Override
7893
public RenderingResponse.Builder cookie(ResponseCookie cookie) {
79-
Assert.notNull(cookie, "'cookie' must not be null");
94+
Assert.notNull(cookie, "ResponseCookie must not be null");
8095
this.cookies.add(cookie.getName(), cookie);
8196
return this;
8297
}
8398

8499
@Override
85100
public RenderingResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
86-
Assert.notNull(cookiesConsumer, "'cookiesConsumer' must not be null");
101+
Assert.notNull(cookiesConsumer, "Consumer must not be null");
87102
cookiesConsumer.accept(this.cookies);
88103
return this;
89104
}
90105

91106
@Override
92107
public RenderingResponse.Builder modelAttribute(Object attribute) {
93-
Assert.notNull(attribute, "'value' must not be null");
108+
Assert.notNull(attribute, "Attribute must not be null");
94109
if (attribute instanceof Collection && ((Collection<?>) attribute).isEmpty()) {
95110
return this;
96111
}
@@ -99,7 +114,7 @@ public RenderingResponse.Builder modelAttribute(Object attribute) {
99114

100115
@Override
101116
public RenderingResponse.Builder modelAttribute(String name, @Nullable Object value) {
102-
Assert.notNull(name, "'name' must not be null");
117+
Assert.notNull(name, "Name must not be null");
103118
this.model.put(name, value);
104119
return this;
105120
}
@@ -138,32 +153,26 @@ public RenderingResponse.Builder headers(HttpHeaders headers) {
138153

139154
@Override
140155
public Mono<RenderingResponse> build() {
141-
return Mono.just(new DefaultRenderingResponse(this.status, this.headers, this.cookies,
142-
this.name, this.model));
156+
return Mono.just(
157+
new DefaultRenderingResponse(this.status, this.headers, this.cookies, this.name, this.model));
143158
}
144159

145160

146-
private final static class DefaultRenderingResponse
147-
extends DefaultServerResponseBuilder.AbstractServerResponse
161+
private static final class DefaultRenderingResponse extends DefaultServerResponseBuilder.AbstractServerResponse
148162
implements RenderingResponse {
149163

150164
private final String name;
151165

152166
private final Map<String, Object> model;
153167

154-
public DefaultRenderingResponse(HttpStatus statusCode, HttpHeaders headers,
155-
MultiValueMap<String, ResponseCookie> cookies,
156-
String name, Map<String, Object> model) {
168+
public DefaultRenderingResponse(int statusCode, HttpHeaders headers,
169+
MultiValueMap<String, ResponseCookie> cookies, String name, Map<String, Object> model) {
170+
157171
super(statusCode, headers, cookies);
158172
this.name = name;
159-
this.model = unmodifiableCopy(model);
173+
this.model = Collections.unmodifiableMap(new LinkedHashMap<>(model));
160174
}
161175

162-
private static <K, V> Map<K, V> unmodifiableCopy(Map<? extends K, ? extends V> m) {
163-
return Collections.unmodifiableMap(new LinkedHashMap<>(m));
164-
}
165-
166-
167176
@Override
168177
public String name() {
169178
return this.name;

0 commit comments

Comments
 (0)