Add ServerRequest.cookies()

This commit introduces a cookies() method on ServerRequest, returning a
MultiValueMap<String, HttpCookie>.

Issue: SPR-15715
This commit is contained in:
Arjen Poutsma 2017-06-30 16:31:37 +02:00
parent 621df7c978
commit 930f0f1760
7 changed files with 126 additions and 10 deletions

View File

@ -20,6 +20,7 @@ import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.Principal; import java.security.Principal;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -32,6 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange; import org.springframework.http.HttpRange;
@ -59,6 +61,8 @@ public class MockServerRequest implements ServerRequest {
private final MockHeaders headers; private final MockHeaders headers;
private final MultiValueMap<String, HttpCookie> cookies;
@Nullable @Nullable
private final Object body; private final Object body;
@ -75,13 +79,15 @@ public class MockServerRequest implements ServerRequest {
private Principal principal; private Principal principal;
private MockServerRequest(HttpMethod method, URI uri, MockHeaders headers, @Nullable Object body, private MockServerRequest(HttpMethod method, URI uri, MockHeaders headers,
MultiValueMap<String, HttpCookie> cookies, @Nullable Object body,
Map<String, Object> attributes, MultiValueMap<String, String> queryParams, Map<String, Object> attributes, MultiValueMap<String, String> queryParams,
Map<String, String> pathVariables, @Nullable WebSession session, @Nullable Principal principal) { Map<String, String> pathVariables, @Nullable WebSession session, @Nullable Principal principal) {
this.method = method; this.method = method;
this.uri = uri; this.uri = uri;
this.headers = headers; this.headers = headers;
this.cookies = cookies;
this.body = body; this.body = body;
this.attributes = attributes; this.attributes = attributes;
this.queryParams = queryParams; this.queryParams = queryParams;
@ -106,6 +112,11 @@ public class MockServerRequest implements ServerRequest {
return this.headers; return this.headers;
} }
@Override
public MultiValueMap<String, HttpCookie> cookies() {
return this.cookies;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor) { public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor) {
@ -182,6 +193,10 @@ public class MockServerRequest implements ServerRequest {
Builder headers(HttpHeaders headers); Builder headers(HttpHeaders headers);
Builder cookie(HttpCookie... cookies);
Builder cookies(MultiValueMap<String, HttpCookie> cookies);
Builder attribute(String name, Object value); Builder attribute(String name, Object value);
Builder attributes(Map<String, Object> attributes); Builder attributes(Map<String, Object> attributes);
@ -212,6 +227,8 @@ public class MockServerRequest implements ServerRequest {
private MockHeaders headers = new MockHeaders(new HttpHeaders()); private MockHeaders headers = new MockHeaders(new HttpHeaders());
private MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
@Nullable @Nullable
private Object body; private Object body;
@ -241,6 +258,19 @@ public class MockServerRequest implements ServerRequest {
return this; return this;
} }
@Override
public Builder cookie(HttpCookie... cookies) {
Arrays.stream(cookies).forEach(cookie -> this.cookies.add(cookie.getName(), cookie));
return this;
}
@Override
public Builder cookies(MultiValueMap<String, HttpCookie> cookies) {
Assert.notNull(cookies, "'cookies' must not be null");
this.cookies = cookies;
return this;
}
@Override @Override
public Builder header(String key, String value) { public Builder header(String key, String value) {
Assert.notNull(key, "'key' must not be null"); Assert.notNull(key, "'key' must not be null");
@ -318,14 +348,14 @@ public class MockServerRequest implements ServerRequest {
@Override @Override
public MockServerRequest body(Object body) { public MockServerRequest body(Object body) {
this.body = body; this.body = body;
return new MockServerRequest(this.method, this.uri, this.headers, this.body, return new MockServerRequest(this.method, this.uri, this.headers, this.cookies,
this.attributes, this.queryParams, this.pathVariables, this.session, this.body, this.attributes, this.queryParams, this.pathVariables, this.session,
this.principal); this.principal);
} }
@Override @Override
public MockServerRequest build() { public MockServerRequest build() {
return new MockServerRequest(this.method, this.uri, this.headers, null, return new MockServerRequest(this.method, this.uri, this.headers, this.cookies, null,
this.attributes, this.queryParams, this.pathVariables, this.session, this.attributes, this.queryParams, this.pathVariables, this.session,
this.principal); this.principal);
} }

View File

@ -32,6 +32,7 @@ import java.util.function.Function;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange; import org.springframework.http.HttpRange;
@ -40,6 +41,7 @@ import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyExtractor;
import org.springframework.web.reactive.function.BodyExtractors; import org.springframework.web.reactive.function.BodyExtractors;
import org.springframework.web.reactive.function.UnsupportedMediaTypeException; import org.springframework.web.reactive.function.UnsupportedMediaTypeException;
@ -95,6 +97,11 @@ class DefaultServerRequest implements ServerRequest {
return this.headers; return this.headers;
} }
@Override
public MultiValueMap<String, HttpCookie> cookies() {
return request().getCookies();
}
@Override @Override
public <T> T body(BodyExtractor<T, ? super ServerHttpRequest> extractor) { public <T> T body(BodyExtractor<T, ? super ServerHttpRequest> extractor) {
return body(extractor, Collections.emptyMap()); return body(extractor, Collections.emptyMap());

View File

@ -34,11 +34,13 @@ import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyExtractor;
import org.springframework.web.server.WebSession; import org.springframework.web.server.WebSession;
import org.springframework.web.util.UriUtils; import org.springframework.web.util.UriUtils;
@ -490,6 +492,11 @@ public abstract class RequestPredicates {
return this.request.headers(); return this.request.headers();
} }
@Override
public MultiValueMap<String, HttpCookie> cookies() {
return this.request.cookies();
}
@Override @Override
public <T> T body(BodyExtractor<T, ? super ServerHttpRequest> extractor) { public <T> T body(BodyExtractor<T, ? super ServerHttpRequest> extractor) {
return this.request.body(extractor); return this.request.body(extractor);

View File

@ -29,6 +29,7 @@ import java.util.OptionalLong;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange; import org.springframework.http.HttpRange;
@ -37,6 +38,7 @@ import org.springframework.http.codec.HttpMessageReader;
import org.springframework.http.codec.json.Jackson2CodecSupport; import org.springframework.http.codec.json.Jackson2CodecSupport;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyExtractor;
import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebSession; import org.springframework.web.server.WebSession;
@ -75,6 +77,11 @@ public interface ServerRequest {
*/ */
Headers headers(); Headers headers();
/**
* Return the cookies of this request.
*/
MultiValueMap<String, HttpCookie> cookies();
/** /**
* Extract the body with the given {@code BodyExtractor}. * Extract the body with the given {@code BodyExtractor}.
* @param extractor the {@code BodyExtractor} that reads from the request * @param extractor the {@code BodyExtractor} that reads from the request

View File

@ -29,12 +29,14 @@ import java.util.OptionalLong;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange; import org.springframework.http.HttpRange;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.MultiValueMap;
import org.springframework.web.reactive.function.BodyExtractor; import org.springframework.web.reactive.function.BodyExtractor;
import org.springframework.web.reactive.function.server.HandlerFunction; import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerRequest;
@ -90,6 +92,11 @@ public class ServerRequestWrapper implements ServerRequest {
return this.delegate.headers(); return this.delegate.headers();
} }
@Override
public MultiValueMap<String, HttpCookie> cookies() {
return this.delegate.cookies();
}
@Override @Override
public <T> T body(BodyExtractor<T, ? super ServerHttpRequest> extractor) { public <T> T body(BodyExtractor<T, ? super ServerHttpRequest> extractor) {
return this.delegate.body(extractor); return this.delegate.body(extractor);

View File

@ -37,6 +37,7 @@ import org.springframework.core.codec.StringDecoder;
import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DefaultDataBuffer; import org.springframework.core.io.buffer.DefaultDataBuffer;
import org.springframework.core.io.buffer.DefaultDataBufferFactory; import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange; import org.springframework.http.HttpRange;
@ -45,6 +46,8 @@ import org.springframework.http.codec.DecoderHttpMessageReader;
import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageReader;
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.test.MockServerWebExchange; import org.springframework.mock.http.server.reactive.test.MockServerWebExchange;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.UnsupportedMediaTypeStatusException; import org.springframework.web.server.UnsupportedMediaTypeStatusException;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@ -176,6 +179,22 @@ public class DefaultServerRequestTests {
assertEquals(httpHeaders, headers.asHttpHeaders()); assertEquals(httpHeaders, headers.asHttpHeaders());
} }
@Test
public void cookies() {
HttpCookie cookie = new HttpCookie("foo", "bar");
MockServerHttpRequest mockRequest = MockServerHttpRequest.method(HttpMethod.GET, "http://example.com").
cookie(cookie).build();
MockServerWebExchange exchange = new MockServerWebExchange(mockRequest);
DefaultServerRequest request = new DefaultServerRequest(exchange, messageReaders);
MultiValueMap<String, HttpCookie> expected = new LinkedMultiValueMap<>();
expected.add("foo", cookie);
assertEquals(expected, request.cookies());
}
@Test @Test
public void body() throws Exception { public void body() throws Exception {
DefaultDataBufferFactory factory = new DefaultDataBufferFactory(); DefaultDataBufferFactory factory = new DefaultDataBufferFactory();

View File

@ -20,6 +20,7 @@ import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.Principal; import java.security.Principal;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -32,6 +33,7 @@ import java.util.concurrent.ConcurrentHashMap;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import org.springframework.http.HttpCookie;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRange; import org.springframework.http.HttpRange;
@ -57,6 +59,9 @@ public class MockServerRequest implements ServerRequest {
private final MockHeaders headers; private final MockHeaders headers;
private final MultiValueMap<String, HttpCookie> cookies;
@Nullable
private final Object body; private final Object body;
private final Map<String, Object> attributes; private final Map<String, Object> attributes;
@ -65,18 +70,21 @@ public class MockServerRequest implements ServerRequest {
private final Map<String, String> pathVariables; private final Map<String, String> pathVariables;
@Nullable
private final WebSession session; private final WebSession session;
@Nullable
private Principal principal; private Principal principal;
private MockServerRequest(HttpMethod method, URI uri, private MockServerRequest(HttpMethod method, URI uri,
MockHeaders headers, @Nullable Object body, Map<String, Object> attributes, MockHeaders headers, MultiValueMap<String, HttpCookie> cookies, @Nullable Object body,
MultiValueMap<String, String> queryParams, Map<String, Object> attributes, MultiValueMap<String, String> queryParams,
Map<String, String> pathVariables, WebSession session, Principal principal) { Map<String, String> pathVariables, @Nullable WebSession session, @Nullable Principal principal) {
this.method = method; this.method = method;
this.uri = uri; this.uri = uri;
this.headers = headers; this.headers = headers;
this.cookies = cookies;
this.body = body; this.body = body;
this.attributes = attributes; this.attributes = attributes;
this.queryParams = queryParams; this.queryParams = queryParams;
@ -101,27 +109,36 @@ public class MockServerRequest implements ServerRequest {
return this.headers; return this.headers;
} }
@Override
public MultiValueMap<String, HttpCookie> cookies() {
return this.cookies;
}
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor){ public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor){
Assert.state(this.body != null, "No body");
return (S) this.body; return (S) this.body;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor, Map<String, Object> hints) { public <S> S body(BodyExtractor<S, ? super ServerHttpRequest> extractor, Map<String, Object> hints) {
Assert.state(this.body != null, "No body");
return (S) this.body; return (S) this.body;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S> Mono<S> bodyToMono(Class<? extends S> elementClass) { public <S> Mono<S> bodyToMono(Class<? extends S> elementClass) {
Assert.state(this.body != null, "No body");
return (Mono<S>) this.body; return (Mono<S>) this.body;
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <S> Flux<S> bodyToFlux(Class<? extends S> elementClass) { public <S> Flux<S> bodyToFlux(Class<? extends S> elementClass) {
Assert.state(this.body != null, "No body");
return (Flux<S>) this.body; return (Flux<S>) this.body;
} }
@ -173,6 +190,10 @@ public class MockServerRequest implements ServerRequest {
Builder headers(HttpHeaders headers); Builder headers(HttpHeaders headers);
Builder cookie(HttpCookie... cookies);
Builder cookies(MultiValueMap<String, HttpCookie> cookies);
Builder attribute(String name, Object value); Builder attribute(String name, Object value);
Builder attributes(Map<String, Object> attributes); Builder attributes(Map<String, Object> attributes);
@ -203,6 +224,9 @@ public class MockServerRequest implements ServerRequest {
private MockHeaders headers = new MockHeaders(new HttpHeaders()); private MockHeaders headers = new MockHeaders(new HttpHeaders());
private MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
@Nullable
private Object body; private Object body;
private Map<String, Object> attributes = new ConcurrentHashMap<>(); private Map<String, Object> attributes = new ConcurrentHashMap<>();
@ -211,8 +235,10 @@ public class MockServerRequest implements ServerRequest {
private Map<String, String> pathVariables = new LinkedHashMap<>(); private Map<String, String> pathVariables = new LinkedHashMap<>();
@Nullable
private WebSession session; private WebSession session;
@Nullable
private Principal principal; private Principal principal;
@Override @Override
@ -244,6 +270,19 @@ public class MockServerRequest implements ServerRequest {
return this; return this;
} }
@Override
public Builder cookie(HttpCookie... cookies) {
Arrays.stream(cookies).forEach(cookie -> this.cookies.add(cookie.getName(), cookie));
return this;
}
@Override
public Builder cookies(MultiValueMap<String, HttpCookie> cookies) {
Assert.notNull(cookies, "'cookies' must not be null");
this.cookies = cookies;
return this;
}
@Override @Override
public Builder attribute(String name, Object value) { public Builder attribute(String name, Object value) {
Assert.notNull(name, "'name' must not be null"); Assert.notNull(name, "'name' must not be null");
@ -306,14 +345,14 @@ public class MockServerRequest implements ServerRequest {
@Override @Override
public MockServerRequest body(Object body) { public MockServerRequest body(Object body) {
this.body = body; this.body = body;
return new MockServerRequest(this.method, this.uri, this.headers, this.body, return new MockServerRequest(this.method, this.uri, this.headers, this.cookies,
this.attributes, this.queryParams, this.pathVariables, this.session, this.body, this.attributes, this.queryParams, this.pathVariables, this.session,
this.principal); this.principal);
} }
@Override @Override
public MockServerRequest build() { public MockServerRequest build() {
return new MockServerRequest(this.method, this.uri, this.headers, null, return new MockServerRequest(this.method, this.uri, this.headers, this.cookies, null,
this.attributes, this.queryParams, this.pathVariables, this.session, this.attributes, this.queryParams, this.pathVariables, this.session,
this.principal); this.principal);
} }