Support for non-standard HTTP status in reactive ClientHttpResponse
Issue: SPR-16748
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -40,6 +40,7 @@ import org.springframework.util.MultiValueMap;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of {@link ClientHttpResponse}.
|
* Mock implementation of {@link ClientHttpResponse}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
@@ -68,6 +69,11 @@ public class MockClientHttpResponse implements ClientHttpResponse {
|
|||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawStatusCode() {
|
||||||
|
return this.status.value();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
String headerName = HttpHeaders.SET_COOKIE;
|
String headerName = HttpHeaders.SET_COOKIE;
|
||||||
|
|||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -31,10 +31,23 @@ import org.springframework.util.MultiValueMap;
|
|||||||
public interface ClientHttpResponse extends ReactiveHttpInputMessage {
|
public interface ClientHttpResponse extends ReactiveHttpInputMessage {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the HTTP status as an {@link HttpStatus} enum value.
|
* Return the HTTP status code of the response.
|
||||||
|
* @return the HTTP status as an HttpStatus enum value
|
||||||
|
* @throws IllegalArgumentException in case of an unknown HTTP status code
|
||||||
|
* @see HttpStatus#valueOf(int)
|
||||||
*/
|
*/
|
||||||
HttpStatus getStatusCode();
|
HttpStatus getStatusCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the HTTP status code (potentially non-standard and not
|
||||||
|
* resolvable through the {@link HttpStatus} enum) as an integer.
|
||||||
|
* @return the HTTP status as an integer
|
||||||
|
* @since 5.0.6
|
||||||
|
* @see #getStatusCode()
|
||||||
|
* @see HttpStatus#resolve(int)
|
||||||
|
*/
|
||||||
|
int getRawStatusCode();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a read-only map of response cookies received from the server.
|
* Return a read-only map of response cookies received from the server.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -55,6 +55,11 @@ public class ClientHttpResponseDecorator implements ClientHttpResponse {
|
|||||||
return this.delegate.getStatusCode();
|
return this.delegate.getStatusCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawStatusCode() {
|
||||||
|
return this.delegate.getRawStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
return this.delegate.getHeaders();
|
return this.delegate.getHeaders();
|
||||||
|
|||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -62,14 +62,18 @@ class ReactorClientHttpResponse implements ClientHttpResponse {
|
|||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
HttpHeaders headers = new HttpHeaders();
|
HttpHeaders headers = new HttpHeaders();
|
||||||
this.response.responseHeaders().entries()
|
this.response.responseHeaders().entries().forEach(e -> headers.add(e.getKey(), e.getValue()));
|
||||||
.forEach(e -> headers.add(e.getKey(), e.getValue()));
|
|
||||||
return headers;
|
return headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpStatus getStatusCode() {
|
public HttpStatus getStatusCode() {
|
||||||
return HttpStatus.valueOf(this.response.status().code());
|
return HttpStatus.valueOf(getRawStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawStatusCode() {
|
||||||
|
return this.response.status().code();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -91,7 +95,7 @@ class ReactorClientHttpResponse implements ClientHttpResponse {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "ReactorClientHttpResponse{" +
|
return "ReactorClientHttpResponse{" +
|
||||||
"request=[" + this.response.method().name() + " " + this.response.uri() + "]," +
|
"request=[" + this.response.method().name() + " " + this.response.uri() + "]," +
|
||||||
"status=" + getStatusCode() + '}';
|
"status=" + getRawStatusCode() + '}';
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2016 the original author or authors.
|
* Copyright 2002-2018 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -40,6 +40,7 @@ import org.springframework.util.MultiValueMap;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock implementation of {@link ClientHttpResponse}.
|
* Mock implementation of {@link ClientHttpResponse}.
|
||||||
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 5.0
|
* @since 5.0
|
||||||
@@ -68,6 +69,11 @@ public class MockClientHttpResponse implements ClientHttpResponse {
|
|||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawStatusCode() {
|
||||||
|
return this.status.value();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
String headerName = HttpHeaders.SET_COOKIE;
|
String headerName = HttpHeaders.SET_COOKIE;
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ public interface ClientRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the attributes of this request.
|
* Return the attributes of this request.
|
||||||
*/
|
*/
|
||||||
@@ -222,8 +221,7 @@ public interface ClientRequest {
|
|||||||
* @param <P> the type of the {@code Publisher}
|
* @param <P> the type of the {@code Publisher}
|
||||||
* @return the built request
|
* @return the built request
|
||||||
*/
|
*/
|
||||||
<S, P extends Publisher<S>> Builder body(P publisher,
|
<S, P extends Publisher<S>> Builder body(P publisher, ParameterizedTypeReference<S> typeReference);
|
||||||
ParameterizedTypeReference<S> typeReference);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the attribute with the given name to the given value.
|
* Set the attribute with the given name to the given value.
|
||||||
@@ -243,8 +241,7 @@ public interface ClientRequest {
|
|||||||
Builder attributes(Consumer<Map<String, Object>> attributesConsumer);
|
Builder attributes(Consumer<Map<String, Object>> attributesConsumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the request.
|
* Build the request.
|
||||||
* @return the request
|
|
||||||
*/
|
*/
|
||||||
ClientRequest build();
|
ClientRequest build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,13 +160,13 @@ public interface ClientResponse {
|
|||||||
* @return the created builder
|
* @return the created builder
|
||||||
*/
|
*/
|
||||||
static Builder from(ClientResponse other) {
|
static Builder from(ClientResponse other) {
|
||||||
Assert.notNull(other, "'other' must not be null");
|
Assert.notNull(other, "Other ClientResponse must not be null");
|
||||||
return new DefaultClientResponseBuilder(other);
|
return new DefaultClientResponseBuilder(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a response builder with the given status code and using default strategies for reading
|
* Create a response builder with the given status code and using default strategies for
|
||||||
* the body.
|
* reading the body.
|
||||||
* @param statusCode the status code
|
* @param statusCode the status code
|
||||||
* @return the created builder
|
* @return the created builder
|
||||||
*/
|
*/
|
||||||
@@ -181,10 +181,7 @@ public interface ClientResponse {
|
|||||||
* @return the created builder
|
* @return the created builder
|
||||||
*/
|
*/
|
||||||
static Builder create(HttpStatus statusCode, ExchangeStrategies strategies) {
|
static Builder create(HttpStatus statusCode, ExchangeStrategies strategies) {
|
||||||
Assert.notNull(statusCode, "'statusCode' must not be null");
|
return new DefaultClientResponseBuilder(strategies).statusCode(statusCode);
|
||||||
Assert.notNull(strategies, "'strategies' must not be null");
|
|
||||||
return new DefaultClientResponseBuilder(strategies)
|
|
||||||
.statusCode(statusCode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -194,24 +191,20 @@ public interface ClientResponse {
|
|||||||
* @return the created builder
|
* @return the created builder
|
||||||
*/
|
*/
|
||||||
static Builder create(HttpStatus statusCode, List<HttpMessageReader<?>> messageReaders) {
|
static Builder create(HttpStatus statusCode, List<HttpMessageReader<?>> messageReaders) {
|
||||||
Assert.notNull(statusCode, "'statusCode' must not be null");
|
|
||||||
Assert.notNull(messageReaders, "'messageReaders' must not be null");
|
|
||||||
|
|
||||||
return create(statusCode, new ExchangeStrategies() {
|
return create(statusCode, new ExchangeStrategies() {
|
||||||
@Override
|
@Override
|
||||||
public List<HttpMessageReader<?>> messageReaders() {
|
public List<HttpMessageReader<?>> messageReaders() {
|
||||||
return messageReaders;
|
return messageReaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<HttpMessageWriter<?>> messageWriters() {
|
public List<HttpMessageWriter<?>> messageWriters() {
|
||||||
// not used in the response
|
// not used in the response
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the headers of the HTTP response.
|
* Represents the headers of the HTTP response.
|
||||||
* @see ClientResponse#headers()
|
* @see ClientResponse#headers()
|
||||||
@@ -243,6 +236,7 @@ public interface ClientResponse {
|
|||||||
HttpHeaders asHttpHeaders();
|
HttpHeaders asHttpHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines a builder for a response.
|
* Defines a builder for a response.
|
||||||
*/
|
*/
|
||||||
@@ -295,7 +289,7 @@ public interface ClientResponse {
|
|||||||
Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer);
|
Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the body of the response. Calling this methods will
|
* Set the body of the response. Calling this methods will
|
||||||
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
|
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
|
||||||
* the existing body of the builder.
|
* the existing body of the builder.
|
||||||
* @param body the new body.
|
* @param body the new body.
|
||||||
@@ -304,7 +298,7 @@ public interface ClientResponse {
|
|||||||
Builder body(Flux<DataBuffer> body);
|
Builder body(Flux<DataBuffer> body);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the body of the response to the UTF-8 encoded bytes of the given string.
|
* Set the body of the response to the UTF-8 encoded bytes of the given string.
|
||||||
* Calling this methods will
|
* Calling this methods will
|
||||||
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
|
* {@linkplain org.springframework.core.io.buffer.DataBufferUtils#release(DataBuffer) release}
|
||||||
* the existing body of the builder.
|
* the existing body of the builder.
|
||||||
@@ -314,9 +308,9 @@ public interface ClientResponse {
|
|||||||
Builder body(String body);
|
Builder body(String body);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds the response.
|
* Build the response.
|
||||||
* @return the response
|
|
||||||
*/
|
*/
|
||||||
ClientResponse build();
|
ClientResponse build();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ class DefaultClientResponse implements ClientResponse {
|
|||||||
this.headers = new DefaultHeaders();
|
this.headers = new DefaultHeaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExchangeStrategies strategies() {
|
public ExchangeStrategies strategies() {
|
||||||
return this.strategies;
|
return this.strategies;
|
||||||
@@ -88,12 +89,10 @@ class DefaultClientResponse implements ClientResponse {
|
|||||||
public List<HttpMessageReader<?>> messageReaders() {
|
public List<HttpMessageReader<?>> messageReaders() {
|
||||||
return strategies.messageReaders();
|
return strategies.messageReaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ServerHttpResponse> serverResponse() {
|
public Optional<ServerHttpResponse> serverResponse() {
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> hints() {
|
public Map<String, Object> hints() {
|
||||||
return Collections.emptyMap();
|
return Collections.emptyMap();
|
||||||
@@ -187,8 +186,7 @@ class DefaultClientResponse implements ClientResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> Mono<ResponseEntity<List<T>>> toEntityList(
|
public <T> Mono<ResponseEntity<List<T>>> toEntityList(ParameterizedTypeReference<T> typeReference) {
|
||||||
ParameterizedTypeReference<T> typeReference) {
|
|
||||||
return toEntityListInternal(bodyToFlux(typeReference));
|
return toEntityListInternal(bodyToFlux(typeReference));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,7 +218,7 @@ class DefaultClientResponse implements ClientResponse {
|
|||||||
@Override
|
@Override
|
||||||
public List<String> header(String headerName) {
|
public List<String> header(String headerName) {
|
||||||
List<String> headerValues = delegate().get(headerName);
|
List<String> headerValues = delegate().get(headerName);
|
||||||
return headerValues != null ? headerValues : Collections.emptyList();
|
return (headerValues != null ? headerValues : Collections.emptyList());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -229,12 +227,13 @@ class DefaultClientResponse implements ClientResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private OptionalLong toOptionalLong(long value) {
|
private OptionalLong toOptionalLong(long value) {
|
||||||
return value != -1 ? OptionalLong.of(value) : OptionalLong.empty();
|
return (value != -1 ? OptionalLong.of(value) : OptionalLong.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
private class ReadCancellationException extends RuntimeException {
|
private static class ReadCancellationException extends RuntimeException {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.springframework.http.HttpHeaders;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseCookie;
|
import org.springframework.http.ResponseCookie;
|
||||||
import org.springframework.http.client.reactive.ClientHttpResponse;
|
import org.springframework.http.client.reactive.ClientHttpResponse;
|
||||||
import org.springframework.lang.Nullable;
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
@@ -55,7 +54,7 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
|
|
||||||
|
|
||||||
public DefaultClientResponseBuilder(ExchangeStrategies strategies) {
|
public DefaultClientResponseBuilder(ExchangeStrategies strategies) {
|
||||||
Assert.notNull(strategies, "'strategies' must not be null");
|
Assert.notNull(strategies, "ExchangeStrategies must not be null");
|
||||||
this.strategies = strategies;
|
this.strategies = strategies;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,9 +65,10 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
cookies(cookies -> cookies.addAll(other.cookies()));
|
cookies(cookies -> cookies.addAll(other.cookies()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DefaultClientResponseBuilder statusCode(HttpStatus statusCode) {
|
public DefaultClientResponseBuilder statusCode(HttpStatus statusCode) {
|
||||||
Assert.notNull(statusCode, "'statusCode' must not be null");
|
Assert.notNull(statusCode, "HttpStatus must not be null");
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientResponse.Builder headers(Consumer<HttpHeaders> headersConsumer) {
|
public ClientResponse.Builder headers(Consumer<HttpHeaders> headersConsumer) {
|
||||||
Assert.notNull(headersConsumer, "'headersConsumer' must not be null");
|
Assert.notNull(headersConsumer, "Consumer must not be null");
|
||||||
headersConsumer.accept(this.headers);
|
headersConsumer.accept(this.headers);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -97,16 +97,15 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientResponse.Builder cookies(
|
public ClientResponse.Builder cookies(Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
|
||||||
Consumer<MultiValueMap<String, ResponseCookie>> cookiesConsumer) {
|
Assert.notNull(cookiesConsumer, "Consumer must not be null");
|
||||||
Assert.notNull(cookiesConsumer, "'cookiesConsumer' must not be null");
|
|
||||||
cookiesConsumer.accept(this.cookies);
|
cookiesConsumer.accept(this.cookies);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientResponse.Builder body(Flux<DataBuffer> body) {
|
public ClientResponse.Builder body(Flux<DataBuffer> body) {
|
||||||
Assert.notNull(body, "'body' must not be null");
|
Assert.notNull(body, "Body must not be null");
|
||||||
releaseBody();
|
releaseBody();
|
||||||
this.body = body;
|
this.body = body;
|
||||||
return this;
|
return this;
|
||||||
@@ -114,7 +113,7 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientResponse.Builder body(String body) {
|
public ClientResponse.Builder body(String body) {
|
||||||
Assert.notNull(body, "'body' must not be null");
|
Assert.notNull(body, "Body must not be null");
|
||||||
releaseBody();
|
releaseBody();
|
||||||
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
|
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
|
||||||
this.body = Flux.just(body).
|
this.body = Flux.just(body).
|
||||||
@@ -131,11 +130,12 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClientResponse build() {
|
public ClientResponse build() {
|
||||||
ClientHttpResponse clientHttpResponse = new BuiltClientHttpResponse(this.statusCode,
|
ClientHttpResponse clientHttpResponse = new BuiltClientHttpResponse(
|
||||||
this.headers, this.cookies, this.body);
|
this.statusCode, this.headers, this.cookies, this.body);
|
||||||
return new DefaultClientResponse(clientHttpResponse, this.strategies);
|
return new DefaultClientResponse(clientHttpResponse, this.strategies);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static class BuiltClientHttpResponse implements ClientHttpResponse {
|
private static class BuiltClientHttpResponse implements ClientHttpResponse {
|
||||||
|
|
||||||
private final HttpStatus statusCode;
|
private final HttpStatus statusCode;
|
||||||
@@ -147,29 +147,24 @@ class DefaultClientResponseBuilder implements ClientResponse.Builder {
|
|||||||
private final Flux<DataBuffer> body;
|
private final Flux<DataBuffer> body;
|
||||||
|
|
||||||
public BuiltClientHttpResponse(HttpStatus statusCode, HttpHeaders headers,
|
public BuiltClientHttpResponse(HttpStatus statusCode, HttpHeaders headers,
|
||||||
MultiValueMap<String, ResponseCookie> cookies,
|
MultiValueMap<String, ResponseCookie> cookies, Flux<DataBuffer> body) {
|
||||||
Flux<DataBuffer> body) {
|
|
||||||
|
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
|
this.headers = HttpHeaders.readOnlyHttpHeaders(headers);
|
||||||
this.cookies = unmodifiableCopy(cookies);
|
this.cookies = CollectionUtils.unmodifiableMultiValueMap(cookies);
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @Nullable <K, V> MultiValueMap<K, V> unmodifiableCopy(@Nullable MultiValueMap<K, V> original) {
|
|
||||||
if (original != null) {
|
|
||||||
return CollectionUtils.unmodifiableMultiValueMap(new LinkedMultiValueMap<>(original));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpStatus getStatusCode() {
|
public HttpStatus getStatusCode() {
|
||||||
return this.statusCode;
|
return this.statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawStatusCode() {
|
||||||
|
return this.statusCode.value();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
return this.headers;
|
return this.headers;
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ public abstract class ExchangeFunctions {
|
|||||||
* @return the created function
|
* @return the created function
|
||||||
*/
|
*/
|
||||||
public static ExchangeFunction create(ClientHttpConnector connector, ExchangeStrategies strategies) {
|
public static ExchangeFunction create(ClientHttpConnector connector, ExchangeStrategies strategies) {
|
||||||
Assert.notNull(connector, "'connector' must not be null");
|
Assert.notNull(connector, "ClientHttpConnector must not be null");
|
||||||
Assert.notNull(strategies, "'strategies' must not be null");
|
Assert.notNull(strategies, "ExchangeStrategies must not be null");
|
||||||
return new DefaultExchangeFunction(connector, strategies);
|
return new DefaultExchangeFunction(connector, strategies);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ public abstract class ExchangeFunctions {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<ClientResponse> exchange(ClientRequest request) {
|
public Mono<ClientResponse> exchange(ClientRequest request) {
|
||||||
Assert.notNull(request, "'request' must not be null");
|
Assert.notNull(request, "ClientRequest must not be null");
|
||||||
return this.connector
|
return this.connector
|
||||||
.connect(request.method(), request.url(),
|
.connect(request.method(), request.url(),
|
||||||
clientHttpRequest -> request.writeTo(clientHttpRequest, this.strategies))
|
clientHttpRequest -> request.writeTo(clientHttpRequest, this.strategies))
|
||||||
@@ -82,9 +82,11 @@ public abstract class ExchangeFunctions {
|
|||||||
.doOnRequest(n -> logger.debug("Demand signaled"))
|
.doOnRequest(n -> logger.debug("Demand signaled"))
|
||||||
.doOnCancel(() -> logger.debug("Cancelling request"))
|
.doOnCancel(() -> logger.debug("Cancelling request"))
|
||||||
.map(response -> {
|
.map(response -> {
|
||||||
HttpStatus status = response.getStatusCode();
|
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Response received, status: " + status + " " + status.getReasonPhrase());
|
int status = response.getRawStatusCode();
|
||||||
|
HttpStatus resolvedStatus = HttpStatus.resolve(status);
|
||||||
|
logger.debug("Response received, status: " + status +
|
||||||
|
(resolvedStatus != null ? " " + resolvedStatus.getReasonPhrase() : ""));
|
||||||
}
|
}
|
||||||
return new DefaultClientResponse(response, this.strategies);
|
return new DefaultClientResponse(response, this.strategies);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -280,12 +280,11 @@ public interface ServerRequest {
|
|||||||
* @param messageReaders the message readers
|
* @param messageReaders the message readers
|
||||||
* @return the created {@code ServerRequest}
|
* @return the created {@code ServerRequest}
|
||||||
*/
|
*/
|
||||||
static ServerRequest create(ServerWebExchange exchange,
|
static ServerRequest create(ServerWebExchange exchange, List<HttpMessageReader<?>> messageReaders) {
|
||||||
List<HttpMessageReader<?>> messageReaders) {
|
|
||||||
|
|
||||||
return new DefaultServerRequest(exchange, messageReaders);
|
return new DefaultServerRequest(exchange, messageReaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the headers of the HTTP request.
|
* Represents the headers of the HTTP request.
|
||||||
* @see ServerRequest#headers()
|
* @see ServerRequest#headers()
|
||||||
|
|||||||
@@ -322,7 +322,6 @@ public interface ServerResponse {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the response entity with no body.
|
* Build the response entity with no body.
|
||||||
* @return the built response
|
|
||||||
*/
|
*/
|
||||||
Mono<ServerResponse> build();
|
Mono<ServerResponse> build();
|
||||||
|
|
||||||
@@ -330,14 +329,12 @@ public interface ServerResponse {
|
|||||||
* Build the response entity with no body.
|
* Build the response entity with no body.
|
||||||
* The response will be committed when the given {@code voidPublisher} completes.
|
* The response will be committed when the given {@code voidPublisher} completes.
|
||||||
* @param voidPublisher publisher publisher to indicate when the response should be committed
|
* @param voidPublisher publisher publisher to indicate when the response should be committed
|
||||||
* @return the built response
|
|
||||||
*/
|
*/
|
||||||
Mono<ServerResponse> build(Publisher<Void> voidPublisher);
|
Mono<ServerResponse> build(Publisher<Void> voidPublisher);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the response entity with a custom writer function.
|
* Build the response entity with a custom writer function.
|
||||||
* @param writeFunction the function used to write to the {@link ServerWebExchange}
|
* @param writeFunction the function used to write to the {@link ServerWebExchange}
|
||||||
* @return the built response
|
|
||||||
*/
|
*/
|
||||||
Mono<ServerResponse> build(BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction);
|
Mono<ServerResponse> build(BiFunction<ServerWebExchange, Context, Mono<Void>> writeFunction);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user