Skip to content

Commit a683472

Browse files
committed
Support for non-standard HTTP status in reactive ClientHttpResponse
Issue: SPR-16748
1 parent 44cf002 commit a683472

File tree

12 files changed

+92
-75
lines changed

12 files changed

+92
-75
lines changed

spring-test/src/main/java/org/springframework/mock/http/client/reactive/MockClientHttpResponse.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 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.
@@ -40,6 +40,7 @@
4040

4141
/**
4242
* Mock implementation of {@link ClientHttpResponse}.
43+
*
4344
* @author Brian Clozel
4445
* @author Rossen Stoyanchev
4546
* @since 5.0
@@ -68,6 +69,11 @@ public HttpStatus getStatusCode() {
6869
return this.status;
6970
}
7071

72+
@Override
73+
public int getRawStatusCode() {
74+
return this.status.value();
75+
}
76+
7177
@Override
7278
public HttpHeaders getHeaders() {
7379
String headerName = HttpHeaders.SET_COOKIE;
@@ -138,4 +144,4 @@ private Charset getCharset() {
138144
return (charset != null ? charset : StandardCharsets.UTF_8);
139145
}
140146

141-
}
147+
}

spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponse.java

Lines changed: 15 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.
@@ -31,10 +31,23 @@
3131
public interface ClientHttpResponse extends ReactiveHttpInputMessage {
3232

3333
/**
34-
* Return the HTTP status as an {@link HttpStatus} enum value.
34+
* Return the HTTP status code of the response.
35+
* @return the HTTP status as an HttpStatus enum value
36+
* @throws IllegalArgumentException in case of an unknown HTTP status code
37+
* @see HttpStatus#valueOf(int)
3538
*/
3639
HttpStatus getStatusCode();
3740

41+
/**
42+
* Return the HTTP status code (potentially non-standard and not
43+
* resolvable through the {@link HttpStatus} enum) as an integer.
44+
* @return the HTTP status as an integer
45+
* @since 5.0.6
46+
* @see #getStatusCode()
47+
* @see HttpStatus#resolve(int)
48+
*/
49+
int getRawStatusCode();
50+
3851
/**
3952
* Return a read-only map of response cookies received from the server.
4053
*/

spring-web/src/main/java/org/springframework/http/client/reactive/ClientHttpResponseDecorator.java

Lines changed: 6 additions & 1 deletion
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.
@@ -55,6 +55,11 @@ public HttpStatus getStatusCode() {
5555
return this.delegate.getStatusCode();
5656
}
5757

58+
@Override
59+
public int getRawStatusCode() {
60+
return this.delegate.getRawStatusCode();
61+
}
62+
5863
@Override
5964
public HttpHeaders getHeaders() {
6065
return this.delegate.getHeaders();

spring-web/src/main/java/org/springframework/http/client/reactive/ReactorClientHttpResponse.java

Lines changed: 9 additions & 5 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.
@@ -62,14 +62,18 @@ public Flux<DataBuffer> getBody() {
6262
@Override
6363
public HttpHeaders getHeaders() {
6464
HttpHeaders headers = new HttpHeaders();
65-
this.response.responseHeaders().entries()
66-
.forEach(e -> headers.add(e.getKey(), e.getValue()));
65+
this.response.responseHeaders().entries().forEach(e -> headers.add(e.getKey(), e.getValue()));
6766
return headers;
6867
}
6968

7069
@Override
7170
public HttpStatus getStatusCode() {
72-
return HttpStatus.valueOf(this.response.status().code());
71+
return HttpStatus.valueOf(getRawStatusCode());
72+
}
73+
74+
@Override
75+
public int getRawStatusCode() {
76+
return this.response.status().code();
7377
}
7478

7579
@Override
@@ -91,7 +95,7 @@ public MultiValueMap<String, ResponseCookie> getCookies() {
9195
public String toString() {
9296
return "ReactorClientHttpResponse{" +
9397
"request=[" + this.response.method().name() + " " + this.response.uri() + "]," +
94-
"status=" + getStatusCode() + '}';
98+
"status=" + getRawStatusCode() + '}';
9599
}
96100

97101
}

spring-web/src/test/java/org/springframework/mock/http/client/reactive/test/MockClientHttpResponse.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 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.
@@ -40,6 +40,7 @@
4040

4141
/**
4242
* Mock implementation of {@link ClientHttpResponse}.
43+
*
4344
* @author Brian Clozel
4445
* @author Rossen Stoyanchev
4546
* @since 5.0
@@ -68,6 +69,11 @@ public HttpStatus getStatusCode() {
6869
return this.status;
6970
}
7071

72+
@Override
73+
public int getRawStatusCode() {
74+
return this.status.value();
75+
}
76+
7177
@Override
7278
public HttpHeaders getHeaders() {
7379
String headerName = HttpHeaders.SET_COOKIE;
@@ -138,4 +144,4 @@ private Charset getCharset() {
138144
return (charset != null ? charset : StandardCharsets.UTF_8);
139145
}
140146

141-
}
147+
}

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ default Optional<Object> attribute(String name) {
8686
}
8787
}
8888

89-
9089
/**
9190
* Return the attributes of this request.
9291
*/
@@ -222,8 +221,7 @@ interface Builder {
222221
* @param <P> the type of the {@code Publisher}
223222
* @return the built request
224223
*/
225-
<S, P extends Publisher<S>> Builder body(P publisher,
226-
ParameterizedTypeReference<S> typeReference);
224+
<S, P extends Publisher<S>> Builder body(P publisher, ParameterizedTypeReference<S> typeReference);
227225

228226
/**
229227
* Set the attribute with the given name to the given value.
@@ -243,8 +241,7 @@ <S, P extends Publisher<S>> Builder body(P publisher,
243241
Builder attributes(Consumer<Map<String, Object>> attributesConsumer);
244242

245243
/**
246-
* Builds the request.
247-
* @return the request
244+
* Build the request.
248245
*/
249246
ClientRequest build();
250247
}

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,13 @@ public interface ClientResponse {
160160
* @return the created builder
161161
*/
162162
static Builder from(ClientResponse other) {
163-
Assert.notNull(other, "'other' must not be null");
163+
Assert.notNull(other, "Other ClientResponse must not be null");
164164
return new DefaultClientResponseBuilder(other);
165165
}
166166

167167
/**
168-
* Create a response builder with the given status code and using default strategies for reading
169-
* the body.
168+
* Create a response builder with the given status code and using default strategies for
169+
* reading the body.
170170
* @param statusCode the status code
171171
* @return the created builder
172172
*/
@@ -181,10 +181,7 @@ static Builder create(HttpStatus statusCode) {
181181
* @return the created builder
182182
*/
183183
static Builder create(HttpStatus statusCode, ExchangeStrategies strategies) {
184-
Assert.notNull(statusCode, "'statusCode' must not be null");
185-
Assert.notNull(strategies, "'strategies' must not be null");
186-
return new DefaultClientResponseBuilder(strategies)
187-
.statusCode(statusCode);
184+
return new DefaultClientResponseBuilder(strategies).statusCode(statusCode);
188185
}
189186

190187
/**
@@ -194,24 +191,20 @@ static Builder create(HttpStatus statusCode, ExchangeStrategies strategies) {
194191
* @return the created builder
195192
*/
196193
static Builder create(HttpStatus statusCode, List<HttpMessageReader<?>> messageReaders) {
197-
Assert.notNull(statusCode, "'statusCode' must not be null");
198-
Assert.notNull(messageReaders, "'messageReaders' must not be null");
199-
200194
return create(statusCode, new ExchangeStrategies() {
201195
@Override
202196
public List<HttpMessageReader<?>> messageReaders() {
203197
return messageReaders;
204198
}
205-
206199
@Override
207200
public List<HttpMessageWriter<?>> messageWriters() {
208201
// not used in the response
209202
return Collections.emptyList();
210203
}
211204
});
212-
213205
}
214206

207+
215208
/**
216209
* Represents the headers of the HTTP response.
217210
* @see ClientResponse#headers()
@@ -243,6 +236,7 @@ interface Headers {
243236
HttpHeaders asHttpHeaders();
244237
}
245238

239+
246240
/**
247241
* Defines a builder for a response.
248242
*/
@@ -295,7 +289,7 @@ interface Builder {
295289
Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer);
296290

297291
/**
298-
* Sets the body of the response. Calling this methods will
292+
* Set the body of the response. Calling this methods will
299293
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
300294
* the existing body of the builder.
301295
* @param body the new body.
@@ -304,7 +298,7 @@ interface Builder {
304298
Builder body(Flux<DataBuffer> body);
305299

306300
/**
307-
* Sets the body of the response to the UTF-8 encoded bytes of the given string.
301+
* Set the body of the response to the UTF-8 encoded bytes of the given string.
308302
* Calling this methods will
309303
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
310304
* the existing body of the builder.
@@ -314,9 +308,9 @@ interface Builder {
314308
Builder body(String body);
315309

316310
/**
317-
* Builds the response.
318-
* @return the response
311+
* Build the response.
319312
*/
320313
ClientResponse build();
321314
}
315+
322316
}

spring-webflux/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public DefaultClientResponse(ClientHttpResponse response, ExchangeStrategies str
6161
this.headers = new DefaultHeaders();
6262
}
6363

64+
6465
@Override
6566
public ExchangeStrategies strategies() {
6667
return this.strategies;
@@ -88,12 +89,10 @@ public <T> T body(BodyExtractor<T, ? super ClientHttpResponse> extractor) {
8889
public List<HttpMessageReader<?>> messageReaders() {
8990
return strategies.messageReaders();
9091
}
91-
9292
@Override
9393
public Optional<ServerHttpResponse> serverResponse() {
9494
return Optional.empty();
9595
}
96-
9796
@Override
9897
public Map<String, Object> hints() {
9998
return Collections.emptyMap();
@@ -187,8 +186,7 @@ public <T> Mono<ResponseEntity<List<T>>> toEntityList(Class<T> responseType) {
187186
}
188187

189188
@Override
190-
public <T> Mono<ResponseEntity<List<T>>> toEntityList(
191-
ParameterizedTypeReference<T> typeReference) {
189+
public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> typeReference) {
192190
return toEntityListInternal(bodyToFlux(typeReference));
193191
}
194192

@@ -220,7 +218,7 @@ public Optional<MediaType> contentType() {
220218
@Override
221219
public List<String> header(String headerName) {
222220
List<String> headerValues = delegate().get(headerName);
223-
return headerValues != null ? headerValues : Collections.emptyList();
221+
return (headerValues != null ? headerValues : Collections.emptyList());
224222
}
225223

226224
@Override
@@ -229,12 +227,13 @@ public HttpHeaders asHttpHeaders() {
229227
}
230228

231229
private OptionalLong toOptionalLong(long value) {
232-
return value != -1 ? OptionalLong.of(value) : OptionalLong.empty();
230+
return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty());
233231
}
234-
235232
}
236233

234+
237235
@SuppressWarnings("serial")
238-
private class ReadCancellationException extends RuntimeException {
236+
private static class ReadCancellationException extends RuntimeException {
239237
}
238+
240239
}

0 commit comments

Comments
 (0)