Refactor reactive mock request and response support
MockServerHttpRequest and MockServerHttpResponse now extend the same abstract base classes that server-specific implementations do and therefore approximate their behavior more closely. As an immediate consequence MockServerHttpRequest is read-only after it is created. Instead it now exposes static builder methods similar to those found in RequestEntity. This enforces more strictness as well as recycling of requests in tests and provides nicer builder methods. To simplify tests DefaultServerWebExchange now offers a constructor with just a request and response, and automatically creating a DefaultWebSessionManager. The spring-test module now also contains client-side reactive mock request and response implementations. The mock client request extends the same AbstractClientHttpRequest as client-specific implementations do. There is no abstract base class for client responses. Issue: SPR-14590
This commit is contained in:
@@ -65,7 +65,7 @@ public class EncoderHttpMessageWriterTests {
|
||||
|
||||
EncoderHttpMessageWriter<ByteBuffer> writer = createWriter(new ByteBufferEncoder());
|
||||
writer.write(source, ResolvableType.forClass(ByteBuffer.class),
|
||||
MediaType.APPLICATION_OCTET_STREAM, this.response, Collections.emptyMap());
|
||||
MediaType.APPLICATION_OCTET_STREAM, this.response, Collections.emptyMap()).blockMillis(5000);
|
||||
|
||||
assertThat(this.response.getHeaders().getContentType(), is(MediaType.APPLICATION_OCTET_STREAM));
|
||||
StepVerifier.create(this.response.getBodyAsString())
|
||||
|
||||
@@ -23,6 +23,8 @@ import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
@@ -60,9 +62,7 @@ public class FormHttpMessageReaderTests {
|
||||
@Test
|
||||
public void readFormAsMono() {
|
||||
String body = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3";
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setBody(body);
|
||||
request.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
MockServerHttpRequest request = request(body);
|
||||
MultiValueMap<String, String> result = this.reader.readMono(null, request, null).block();
|
||||
|
||||
assertEquals("Invalid result", 3, result.size());
|
||||
@@ -77,9 +77,7 @@ public class FormHttpMessageReaderTests {
|
||||
@Test
|
||||
public void readFormAsFlux() {
|
||||
String body = "name+1=value+1&name+2=value+2%2B1&name+2=value+2%2B2&name+3";
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setBody(body);
|
||||
request.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
MockServerHttpRequest request = request(body);
|
||||
MultiValueMap<String, String> result = this.reader.read(null, request, null).single().block();
|
||||
|
||||
assertEquals("Invalid result", 3, result.size());
|
||||
@@ -91,4 +89,11 @@ public class FormHttpMessageReaderTests {
|
||||
assertNull("Invalid result", result.getFirst("name 3"));
|
||||
}
|
||||
|
||||
private MockServerHttpRequest request(String body) {
|
||||
return MockServerHttpRequest
|
||||
.method(HttpMethod.GET, "/")
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
|
||||
.body(body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.http.codec;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -35,8 +36,10 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.util.MimeTypeUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ResourceHttpMessageWriter}.
|
||||
@@ -47,8 +50,6 @@ public class ResourceHttpMessageWriterTests {
|
||||
|
||||
private ResourceHttpMessageWriter writer = new ResourceHttpMessageWriter();
|
||||
|
||||
private MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
|
||||
private MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
|
||||
private Resource resource;
|
||||
@@ -69,14 +70,8 @@ public class ResourceHttpMessageWriterTests {
|
||||
|
||||
@Test
|
||||
public void shouldWriteResource() throws Exception {
|
||||
|
||||
Mono<Void> mono = this.writer.write(Mono.just(resource), null,
|
||||
ResolvableType.forClass(Resource.class),
|
||||
MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap());
|
||||
StepVerifier.create(mono)
|
||||
.expectNextCount(0)
|
||||
.expectComplete()
|
||||
.verify();
|
||||
MockServerHttpRequest request = get("/").build();
|
||||
testWrite(request);
|
||||
|
||||
assertThat(this.response.getHeaders().getContentType(), is(MediaType.TEXT_PLAIN));
|
||||
assertThat(this.response.getHeaders().getContentLength(), is(39L));
|
||||
@@ -91,13 +86,8 @@ public class ResourceHttpMessageWriterTests {
|
||||
|
||||
@Test
|
||||
public void shouldWriteResourceRange() throws Exception {
|
||||
this.request.getHeaders().setRange(Collections.singletonList(HttpRange.createByteRange(0, 5)));
|
||||
Mono<Void> mono = this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class),
|
||||
MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap());
|
||||
StepVerifier.create(mono)
|
||||
.expectNextCount(0)
|
||||
.expectComplete()
|
||||
.verify();
|
||||
MockServerHttpRequest request = get("/").range(HttpRange.createByteRange(0, 5)).build();
|
||||
testWrite(request);
|
||||
|
||||
assertThat(this.response.getHeaders().getContentType(), is(MediaType.TEXT_PLAIN));
|
||||
assertThat(this.response.getHeaders().getFirst(HttpHeaders.CONTENT_RANGE), is("bytes 0-5/39"));
|
||||
@@ -105,25 +95,25 @@ public class ResourceHttpMessageWriterTests {
|
||||
assertThat(this.response.getHeaders().getContentLength(), is(6L));
|
||||
|
||||
Mono<String> result = this.response.getBodyAsString();
|
||||
StepVerifier.create(result)
|
||||
.expectNext("Spring")
|
||||
.expectComplete()
|
||||
.verify();
|
||||
StepVerifier.create(result).expectNext("Spring").expectComplete().verify();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldSetRangeNotSatisfiableStatus() throws Exception {
|
||||
this.request.getHeaders().set(HttpHeaders.RANGE, "invalid");
|
||||
|
||||
Mono<Void> mono = this.writer.write(Mono.just(resource), null, ResolvableType.forClass(Resource.class),
|
||||
MediaType.TEXT_PLAIN, this.request, this.response, Collections.emptyMap());
|
||||
StepVerifier.create(mono)
|
||||
.expectNextCount(0)
|
||||
.expectComplete()
|
||||
.verify();
|
||||
MockServerHttpRequest request = get("/").header(HttpHeaders.RANGE, "invalid").build();
|
||||
testWrite(request);
|
||||
|
||||
assertThat(this.response.getHeaders().getFirst(HttpHeaders.ACCEPT_RANGES), is("bytes"));
|
||||
assertThat(this.response.getStatusCode(), is(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE));
|
||||
}
|
||||
|
||||
private void testWrite(MockServerHttpRequest request) {
|
||||
Mono<Resource> input = Mono.just(this.resource);
|
||||
ResolvableType type = ResolvableType.forClass(Resource.class);
|
||||
MediaType contentType = MediaType.TEXT_PLAIN;
|
||||
Map<String, Object> hints = Collections.emptyMap();
|
||||
Mono<Void> mono = this.writer.write(input, null, type, contentType, request, this.response, hints);
|
||||
StepVerifier.create(mono).expectNextCount(0).expectComplete().verify();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,9 +19,6 @@ package org.springframework.http.codec;
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.test.StepVerifier;
|
||||
@@ -32,6 +29,10 @@ import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.Jackson2JsonDecoder;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
@@ -57,10 +58,12 @@ public class ServerSentEventHttpMessageReaderTests extends AbstractDataBufferAll
|
||||
|
||||
@Test
|
||||
public void readServerSentEvents() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setBody("id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n" +
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(
|
||||
"id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n\n" +
|
||||
"id:c43\nevent:bar\nretry:456\ndata:baz\n\n");
|
||||
Flux<ServerSentEvent> events = messageReader
|
||||
|
||||
Flux<ServerSentEvent> events = this.messageReader
|
||||
.read(ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class),
|
||||
request, Collections.emptyMap()).cast(ServerSentEvent.class);
|
||||
|
||||
@@ -85,9 +88,13 @@ public class ServerSentEventHttpMessageReaderTests extends AbstractDataBufferAll
|
||||
|
||||
@Test
|
||||
public void readServerSentEventsWithMultipleChunks() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setBody(Flux.just(stringBuffer("id:c42\nev"), stringBuffer("ent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:"),
|
||||
stringBuffer("bar\n\nid:c43\nevent:bar\nretry:456\ndata:baz\n\n")));
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest.post("/")
|
||||
.body(Flux.just(
|
||||
stringBuffer("id:c42\nev"),
|
||||
stringBuffer("ent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:"),
|
||||
stringBuffer("bar\n\nid:c43\nevent:bar\nretry:456\ndata:baz\n\n")));
|
||||
|
||||
Flux<ServerSentEvent> events = messageReader
|
||||
.read(ResolvableType.forClassWithGenerics(ServerSentEvent.class, String.class),
|
||||
request, Collections.emptyMap()).cast(ServerSentEvent.class);
|
||||
@@ -113,8 +120,10 @@ public class ServerSentEventHttpMessageReaderTests extends AbstractDataBufferAll
|
||||
|
||||
@Test
|
||||
public void readString() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setBody("data:foo\ndata:bar\n\ndata:baz\n\n");
|
||||
|
||||
String body = "data:foo\ndata:bar\n\ndata:baz\n\n";
|
||||
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(body);
|
||||
|
||||
Flux<String> data = messageReader.read(ResolvableType.forClass(String.class),
|
||||
request, Collections.emptyMap()).cast(String.class);
|
||||
|
||||
@@ -127,9 +136,11 @@ public class ServerSentEventHttpMessageReaderTests extends AbstractDataBufferAll
|
||||
|
||||
@Test
|
||||
public void readPojo() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setBody("data:{\"foo\": \"foofoo\", \"bar\": \"barbar\"}\n\n" +
|
||||
"data:{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}\n\n");
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest.post("/").body(
|
||||
"data:{\"foo\": \"foofoo\", \"bar\": \"barbar\"}\n\n" +
|
||||
"data:{\"foo\": \"foofoofoo\", \"bar\": \"barbarbar\"}\n\n");
|
||||
|
||||
Flux<Pojo> data = messageReader.read(ResolvableType.forClass(Pojo.class), request,
|
||||
Collections.emptyMap()).cast(Pojo.class);
|
||||
|
||||
|
||||
@@ -18,24 +18,22 @@ package org.springframework.http.codec;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.Test;
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.io.buffer.AbstractDataBufferAllocatingTestCase;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.json.Jackson2JsonEncoder;
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Sebastien Deleuze
|
||||
@@ -69,12 +67,16 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll
|
||||
Mono<ServerSentEvent<String>> source = Mono.just(event);
|
||||
MockServerHttpResponse outputMessage = new MockServerHttpResponse();
|
||||
messageWriter.write(source, ResolvableType.forClass(ServerSentEvent.class),
|
||||
new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap());
|
||||
new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()).blockMillis(5000);
|
||||
|
||||
Publisher<? extends Publisher<? extends DataBuffer>> result = Flux.from(outputMessage.getBodyWithFlush());
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(sseConsumer(
|
||||
"id:c42\nevent:foo\nretry:123\n:bla\n:bla bla\n:bla bla bla\ndata:bar\n"))
|
||||
StepVerifier.create(outputMessage.getBodyAsString())
|
||||
.expectNext("id:c42\n" +
|
||||
"event:foo\n" +
|
||||
"retry:123\n" +
|
||||
":bla\n" +
|
||||
":bla bla\n" +
|
||||
":bla bla bla\n" +
|
||||
"data:bar\n\n")
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -84,12 +86,10 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll
|
||||
Flux<String> source = Flux.just("foo", "bar");
|
||||
MockServerHttpResponse outputMessage = new MockServerHttpResponse();
|
||||
messageWriter.write(source, ResolvableType.forClass(String.class),
|
||||
new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap());
|
||||
new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()).blockMillis(5000);
|
||||
|
||||
Publisher<? extends Publisher<? extends DataBuffer>> result = outputMessage.getBodyWithFlush();
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(sseConsumer("data:foo\n"))
|
||||
.consumeNextWith(sseConsumer("data:bar\n"))
|
||||
StepVerifier.create(outputMessage.getBodyAsString())
|
||||
.expectNext("data:foo\n\ndata:bar\n\n")
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -99,12 +99,13 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll
|
||||
Flux<String> source = Flux.just("foo\nbar", "foo\nbaz");
|
||||
MockServerHttpResponse outputMessage = new MockServerHttpResponse();
|
||||
messageWriter.write(source, ResolvableType.forClass(String.class),
|
||||
new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap());
|
||||
new MediaType("text", "event-stream"), outputMessage, Collections.emptyMap()).blockMillis(5000);
|
||||
|
||||
Publisher<? extends Publisher<? extends DataBuffer>> result = outputMessage.getBodyWithFlush();
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(sseConsumer("data:foo\ndata:bar\n"))
|
||||
.consumeNextWith(sseConsumer("data:foo\ndata:baz\n"))
|
||||
StepVerifier.create(outputMessage.getBodyAsString())
|
||||
.expectNext("data:foo\n" +
|
||||
"data:bar\n\n" +
|
||||
"data:foo\n" +
|
||||
"data:baz\n\n")
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -115,12 +116,11 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll
|
||||
new Pojo("foofoofoo", "barbarbar"));
|
||||
MockServerHttpResponse outputMessage = new MockServerHttpResponse();
|
||||
messageWriter.write(source, ResolvableType.forClass(Pojo.class),
|
||||
MediaType.TEXT_EVENT_STREAM, outputMessage, Collections.emptyMap());
|
||||
MediaType.TEXT_EVENT_STREAM, outputMessage, Collections.emptyMap()).blockMillis(5000);
|
||||
|
||||
Publisher<? extends Publisher<? extends DataBuffer>> result = outputMessage.getBodyWithFlush();
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(sseConsumer("data:", "{\"foo\":\"foofoo\",\"bar\":\"barbar\"}", "\n"))
|
||||
.consumeNextWith(sseConsumer("data:", "{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}", "\n"))
|
||||
StepVerifier.create(outputMessage.getBodyAsString())
|
||||
.expectNext("data:{\"foo\":\"foofoo\",\"bar\":\"barbar\"}\n\n" +
|
||||
"data:{\"foo\":\"foofoofoo\",\"bar\":\"barbarbar\"}\n\n")
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
@@ -128,35 +128,24 @@ public class ServerSentEventHttpMessageWriterTests extends AbstractDataBufferAll
|
||||
@Test // SPR-14899
|
||||
public void writePojoWithPrettyPrint() {
|
||||
ObjectMapper mapper = Jackson2ObjectMapperBuilder.json().indentOutput(true).build();
|
||||
this.messageWriter = new ServerSentEventHttpMessageWriter(Collections.singletonList(new Jackson2JsonEncoder(mapper)));
|
||||
this.messageWriter = new ServerSentEventHttpMessageWriter(
|
||||
Collections.singletonList(new Jackson2JsonEncoder(mapper)));
|
||||
|
||||
Flux<Pojo> source = Flux.just(new Pojo("foofoo", "barbar"),
|
||||
new Pojo("foofoofoo", "barbarbar"));
|
||||
MockServerHttpResponse outputMessage = new MockServerHttpResponse();
|
||||
messageWriter.write(source, ResolvableType.forClass(Pojo.class),
|
||||
MediaType.TEXT_EVENT_STREAM, outputMessage, Collections.emptyMap());
|
||||
MediaType.TEXT_EVENT_STREAM, outputMessage, Collections.emptyMap()).blockMillis(5000);
|
||||
|
||||
Publisher<? extends Publisher<? extends DataBuffer>> result = outputMessage.getBodyWithFlush();
|
||||
StepVerifier.create(result)
|
||||
.consumeNextWith(sseConsumer("data:", "{\n" +
|
||||
StepVerifier.create(outputMessage.getBodyAsString())
|
||||
.expectNext("data:{\n" +
|
||||
"data: \"foo\" : \"foofoo\",\n" +
|
||||
"data: \"bar\" : \"barbar\"\n" + "data:}", "\n"))
|
||||
.consumeNextWith(sseConsumer("data:", "{\n" +
|
||||
"data: \"bar\" : \"barbar\"\n" + "data:}\n\n" +
|
||||
"data:{\n" +
|
||||
"data: \"foo\" : \"foofoofoo\",\n" +
|
||||
"data: \"bar\" : \"barbarbar\"\n" + "data:}", "\n"))
|
||||
"data: \"bar\" : \"barbarbar\"\n" + "data:}\n\n")
|
||||
.expectComplete()
|
||||
.verify();
|
||||
}
|
||||
|
||||
|
||||
private Consumer<Publisher<? extends DataBuffer>> sseConsumer(String... expected) {
|
||||
return publisher -> {
|
||||
StepVerifier.Step<DataBuffer> builder = StepVerifier.create(publisher);
|
||||
for (String value : expected) {
|
||||
builder = builder.consumeNextWith(stringConsumer(value));
|
||||
}
|
||||
builder.consumeNextWith(stringConsumer("\n")).expectComplete().verify();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import java.util.Map;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
@@ -94,8 +93,10 @@ public class HttpHandlerAdapterSupportTests {
|
||||
|
||||
@Test
|
||||
public void matchWithNativeContextPath() throws Exception {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/yet/another/path");
|
||||
request.setContextPath("/yet"); // contextPath in underlying request
|
||||
MockServerHttpRequest request = MockServerHttpRequest
|
||||
.get("/yet/another/path")
|
||||
.contextPath("/yet") // contextPath in underlying request
|
||||
.build();
|
||||
|
||||
TestHttpHandler handler = new TestHttpHandler();
|
||||
Map<String, HttpHandler> map = Collections.singletonMap("/another/path", handler);
|
||||
@@ -145,7 +146,7 @@ public class HttpHandlerAdapterSupportTests {
|
||||
}
|
||||
|
||||
public ServerHttpResponse handle(String path) {
|
||||
ServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, path);
|
||||
ServerHttpRequest request = MockServerHttpRequest.get(path).build();
|
||||
return handle(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.client.reactive.test;
|
||||
package org.springframework.mock.http.client.reactive.test;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
@@ -28,60 +28,43 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.client.reactive.AbstractClientHttpRequest;
|
||||
import org.springframework.http.client.reactive.ClientHttpRequest;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ClientHttpRequest}.
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockClientHttpRequest extends AbstractClientHttpRequest {
|
||||
|
||||
private HttpMethod httpMethod;
|
||||
|
||||
private URI uri;
|
||||
private URI url;
|
||||
|
||||
private final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();
|
||||
|
||||
private Flux<DataBuffer> body;
|
||||
|
||||
private Flux<Publisher<DataBuffer>> bodyWithFlushes;
|
||||
|
||||
|
||||
public MockClientHttpRequest() {
|
||||
public MockClientHttpRequest(HttpMethod httpMethod, String urlTemplate, Object... vars) {
|
||||
this(httpMethod, UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(vars).encode().toUri());
|
||||
}
|
||||
|
||||
public MockClientHttpRequest(HttpMethod httpMethod, String uri) {
|
||||
this(httpMethod, (uri != null ? URI.create(uri) : null));
|
||||
}
|
||||
|
||||
public MockClientHttpRequest(HttpMethod httpMethod, URI uri) {
|
||||
super();
|
||||
public MockClientHttpRequest(HttpMethod httpMethod, URI url) {
|
||||
this.httpMethod = httpMethod;
|
||||
this.uri = uri;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return this.httpMethod;
|
||||
}
|
||||
|
||||
public MockClientHttpRequest setMethod(HttpMethod httpMethod) {
|
||||
this.httpMethod = httpMethod;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return this.uri;
|
||||
}
|
||||
|
||||
public MockClientHttpRequest setUri(String uri) {
|
||||
this.uri = URI.create(uri);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockClientHttpRequest setUri(URI uri) {
|
||||
this.uri = uri;
|
||||
return this;
|
||||
return this.url;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -89,34 +72,35 @@ public class MockClientHttpRequest extends AbstractClientHttpRequest {
|
||||
return this.bufferFactory;
|
||||
}
|
||||
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
||||
this.body = Flux.from(body);
|
||||
return doCommit(() -> this.body.then());
|
||||
return doCommit(() -> {
|
||||
this.body = Flux.from(body);
|
||||
return Mono.empty();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
|
||||
this.bodyWithFlushes = Flux.from(body).map(p -> Flux.from(p));
|
||||
return doCommit(() -> this.bodyWithFlushes.then());
|
||||
return writeWith(Flux.from(body).flatMap(p -> p));
|
||||
}
|
||||
|
||||
public Publisher<DataBuffer> getBody() {
|
||||
return body;
|
||||
@Override
|
||||
protected void applyHeaders() {
|
||||
}
|
||||
|
||||
public Publisher<Publisher<DataBuffer>> getBodyWithFlush() {
|
||||
return bodyWithFlushes;
|
||||
@Override
|
||||
protected void applyCookies() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> setComplete() {
|
||||
return doCommit().then();
|
||||
return doCommit(Mono::empty);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyHeaders() { }
|
||||
|
||||
@Override
|
||||
protected void applyCookies() { }
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.client.reactive.test;
|
||||
package org.springframework.mock.http.client.reactive.test;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
@@ -22,23 +22,30 @@ import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.client.reactive.ClientHttpResponse;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ClientHttpResponse}.
|
||||
* @author Brian Clozel
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockClientHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private HttpStatus status;
|
||||
private final HttpStatus status;
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
@@ -46,60 +53,80 @@ public class MockClientHttpResponse implements ClientHttpResponse {
|
||||
|
||||
private Flux<DataBuffer> body = Flux.empty();
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return headers;
|
||||
private final DataBufferFactory bufferFactory = new DefaultDataBufferFactory();
|
||||
|
||||
|
||||
public MockClientHttpResponse(HttpStatus status) {
|
||||
Assert.notNull(status, "HttpStatus is required");
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public MockClientHttpResponse addHeader(String name, String value) {
|
||||
getHeaders().add(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockClientHttpResponse setHeader(String name, String value) {
|
||||
getHeaders().set(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpStatus getStatusCode() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public void setStatus(HttpStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
public HttpHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
public MockClientHttpResponse setBody(Publisher<DataBuffer> body) {
|
||||
public MultiValueMap<String, ResponseCookie> getCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
public void setBody(Publisher<DataBuffer> body) {
|
||||
this.body = Flux.from(body);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockClientHttpResponse setBody(String body) {
|
||||
DataBuffer buffer = toDataBuffer(body, StandardCharsets.UTF_8);
|
||||
this.body = Flux.just(buffer);
|
||||
return this;
|
||||
public void setBody(String body) {
|
||||
setBody(body, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public MockClientHttpResponse setBody(String body, Charset charset) {
|
||||
public void setBody(String body, Charset charset) {
|
||||
DataBuffer buffer = toDataBuffer(body, charset);
|
||||
this.body = Flux.just(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
private DataBuffer toDataBuffer(String body, Charset charset) {
|
||||
byte[] bytes = body.getBytes(charset);
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
return new DefaultDataBufferFactory().wrap(byteBuffer);
|
||||
return this.bufferFactory.wrap(byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, ResponseCookie> getCookies() {
|
||||
return this.cookies;
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the response body aggregated and converted to a String using the
|
||||
* charset of the Content-Type response or otherwise as "UTF-8".
|
||||
*/
|
||||
public Mono<String> getBodyAsString() {
|
||||
Charset charset = getCharset();
|
||||
return Flux.from(getBody())
|
||||
.reduce(bufferFactory.allocateBuffer(), (previous, current) -> {
|
||||
previous.write(current);
|
||||
DataBufferUtils.release(current);
|
||||
return previous;
|
||||
})
|
||||
.map(buffer -> dumpString(buffer, charset));
|
||||
}
|
||||
|
||||
private static String dumpString(DataBuffer buffer, Charset charset) {
|
||||
Assert.notNull(charset, "'charset' must not be null");
|
||||
byte[] bytes = new byte[buffer.readableByteCount()];
|
||||
buffer.read(bytes);
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
|
||||
private Charset getCharset() {
|
||||
Charset charset = null;
|
||||
MediaType contentType = getHeaders().getContentType();
|
||||
if (contentType != null) {
|
||||
charset = contentType.getCharset();
|
||||
}
|
||||
return (charset != null ? charset : StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -19,6 +19,8 @@ import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
@@ -28,140 +30,394 @@ import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.http.HttpCookie;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpRange;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.server.reactive.AbstractServerHttpRequest;
|
||||
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.util.UriComponentsBuilder;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ServerHttpRequest}.
|
||||
*
|
||||
* <p><strong>Note:</strong> this class extends the same
|
||||
* {@link AbstractServerHttpRequest} base class as actual server-specific
|
||||
* implementation and is therefore read-only once created. Use static builder
|
||||
* methods in this class to build up request instances.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockServerHttpRequest implements ServerHttpRequest {
|
||||
public class MockServerHttpRequest extends AbstractServerHttpRequest {
|
||||
|
||||
private HttpMethod httpMethod;
|
||||
private final HttpMethod httpMethod;
|
||||
|
||||
private URI url;
|
||||
private final String contextPath;
|
||||
|
||||
private String contextPath = "";
|
||||
private final MultiValueMap<String, HttpCookie> cookies;
|
||||
|
||||
private final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private final MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
|
||||
|
||||
private Flux<DataBuffer> body = Flux.empty();
|
||||
private final Flux<DataBuffer> body;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance where the HTTP method and/or URL can be set later
|
||||
* via {@link #setHttpMethod(HttpMethod)} and {@link #setUri(URI)}.
|
||||
*/
|
||||
public MockServerHttpRequest() {
|
||||
}
|
||||
private MockServerHttpRequest(HttpMethod httpMethod, URI uri, String contextPath,
|
||||
HttpHeaders headers, MultiValueMap<String, HttpCookie> cookies,
|
||||
Publisher<? extends DataBuffer> body) {
|
||||
|
||||
/**
|
||||
* Convenience alternative to {@link #MockServerHttpRequest(HttpMethod, URI)}
|
||||
* that accepts a String URL.
|
||||
*/
|
||||
public MockServerHttpRequest(HttpMethod httpMethod, String url) {
|
||||
this(httpMethod, (url != null ? URI.create(url) : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with the given HTTP method and URL.
|
||||
*/
|
||||
public MockServerHttpRequest(HttpMethod httpMethod, URI url) {
|
||||
super(uri, headers);
|
||||
this.httpMethod = httpMethod;
|
||||
this.url = url;
|
||||
this.contextPath = (contextPath != null ? contextPath : "");
|
||||
this.cookies = cookies;
|
||||
this.body = Flux.from(body);
|
||||
}
|
||||
|
||||
|
||||
public void setHttpMethod(HttpMethod httpMethod) {
|
||||
this.httpMethod = httpMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpMethod getMethod() {
|
||||
return this.httpMethod;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest setUri(String url) {
|
||||
this.url = URI.create(url);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest setUri(URI uri) {
|
||||
this.url = uri;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI getURI() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
public void setContextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getContextPath() {
|
||||
return this.contextPath;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest addHeader(String name, String value) {
|
||||
getHeaders().add(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest setHeader(String name, String value) {
|
||||
getHeaders().set(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, String> getQueryParams() {
|
||||
return this.queryParams;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, HttpCookie> getCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest setBody(Publisher<DataBuffer> body) {
|
||||
this.body = Flux.from(body);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest setBody(String body) {
|
||||
DataBuffer buffer = toDataBuffer(body, StandardCharsets.UTF_8);
|
||||
this.body = Flux.just(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MockServerHttpRequest setBody(String body, Charset charset) {
|
||||
DataBuffer buffer = toDataBuffer(body, charset);
|
||||
this.body = Flux.just(buffer);
|
||||
return this;
|
||||
}
|
||||
|
||||
private DataBuffer toDataBuffer(String body, Charset charset) {
|
||||
byte[] bytes = body.getBytes(charset);
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
return new DefaultDataBufferFactory().wrap(byteBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
}
|
||||
@Override
|
||||
protected MultiValueMap<String, HttpCookie> initCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
// Static builder methods
|
||||
|
||||
/**
|
||||
* Create a builder with the given HTTP method and a {@link URI}.
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param url the URL
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder method(HttpMethod method, URI url) {
|
||||
return new DefaultBodyBuilder(method, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative to {@link #method(HttpMethod, URI)} that accepts a URI template.
|
||||
* @param method the HTTP method (GET, POST, etc)
|
||||
* @param urlTemplate the URL template
|
||||
* @param vars variables to expand into the template
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder method(HttpMethod method, String urlTemplate, Object... vars) {
|
||||
URI url = UriComponentsBuilder.fromUriString(urlTemplate).buildAndExpand(vars).encode().toUri();
|
||||
return new DefaultBodyBuilder(method, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP GET builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> get(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.GET, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP HEAD builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> head(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.HEAD, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP POST builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder post(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.POST, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP PUT builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder put(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.PUT, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP PATCH builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BodyBuilder patch(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.PATCH, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an HTTP DELETE builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> delete(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.DELETE, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an HTTP OPTIONS builder with the given url.
|
||||
* @param urlTemplate a URL template; the resulting URL will be encoded
|
||||
* @param uriVars zero or more URI variables
|
||||
* @return the created builder
|
||||
*/
|
||||
public static BaseBuilder<?> options(String urlTemplate, Object... uriVars) {
|
||||
return method(HttpMethod.OPTIONS, urlTemplate, uriVars);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Defines a builder that adds headers to the request.
|
||||
* @param <B> the builder subclass
|
||||
*/
|
||||
public interface BaseBuilder<B extends BaseBuilder<B>> {
|
||||
|
||||
/**
|
||||
* Set the contextPath to return.
|
||||
*/
|
||||
B contextPath(String contextPath);
|
||||
|
||||
/**
|
||||
* Add one or more cookies.
|
||||
*/
|
||||
B cookie(String path, HttpCookie... cookie);
|
||||
|
||||
/**
|
||||
* Add the given, single header value under the given name.
|
||||
* @param headerName the header name
|
||||
* @param headerValues the header value(s)
|
||||
* @see HttpHeaders#add(String, String)
|
||||
*/
|
||||
B header(String headerName, String... headerValues);
|
||||
|
||||
/**
|
||||
* Set the list of acceptable {@linkplain MediaType media types}, as
|
||||
* specified by the {@code Accept} header.
|
||||
* @param acceptableMediaTypes the acceptable media types
|
||||
*/
|
||||
B accept(MediaType... acceptableMediaTypes);
|
||||
|
||||
/**
|
||||
* Set the list of acceptable {@linkplain Charset charsets}, as specified
|
||||
* by the {@code Accept-Charset} header.
|
||||
* @param acceptableCharsets the acceptable charsets
|
||||
*/
|
||||
B acceptCharset(Charset... acceptableCharsets);
|
||||
|
||||
/**
|
||||
* Set the value of the {@code If-Modified-Since} header.
|
||||
* <p>The date should be specified as the number of milliseconds since
|
||||
* January 1, 1970 GMT.
|
||||
* @param ifModifiedSince the new value of the header
|
||||
*/
|
||||
B ifModifiedSince(long ifModifiedSince);
|
||||
|
||||
/**
|
||||
* Set the (new) value of the {@code If-Unmodified-Since} header.
|
||||
* <p>The date should be specified as the number of milliseconds since
|
||||
* January 1, 1970 GMT.
|
||||
* @param ifUnmodifiedSince the new value of the header
|
||||
* @see HttpHeaders#setIfUnmodifiedSince(long)
|
||||
*/
|
||||
B ifUnmodifiedSince(long ifUnmodifiedSince);
|
||||
|
||||
/**
|
||||
* Set the values of the {@code If-None-Match} header.
|
||||
* @param ifNoneMatches the new value of the header
|
||||
*/
|
||||
B ifNoneMatch(String... ifNoneMatches);
|
||||
|
||||
/**
|
||||
* Set the (new) value of the Range header.
|
||||
* @param ranges the HTTP ranges
|
||||
* @see HttpHeaders#setRange(List)
|
||||
*/
|
||||
B range(HttpRange... ranges);
|
||||
|
||||
/**
|
||||
* Builds the request with no body.
|
||||
* @return the request
|
||||
* @see BodyBuilder#body(Publisher)
|
||||
* @see BodyBuilder#body(String)
|
||||
*/
|
||||
MockServerHttpRequest build();
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder that adds a body to the request.
|
||||
*/
|
||||
public interface BodyBuilder extends BaseBuilder<BodyBuilder> {
|
||||
|
||||
/**
|
||||
* Set the length of the body in bytes, as specified by the
|
||||
* {@code Content-Length} header.
|
||||
* @param contentLength the content length
|
||||
* @return this builder
|
||||
* @see HttpHeaders#setContentLength(long)
|
||||
*/
|
||||
BodyBuilder contentLength(long contentLength);
|
||||
|
||||
/**
|
||||
* Set the {@linkplain MediaType media type} of the body, as specified
|
||||
* by the {@code Content-Type} header.
|
||||
* @param contentType the content type
|
||||
* @return this builder
|
||||
* @see HttpHeaders#setContentType(MediaType)
|
||||
*/
|
||||
BodyBuilder contentType(MediaType contentType);
|
||||
|
||||
/**
|
||||
* Set the body of the request and build it.
|
||||
* @param body the body
|
||||
* @return the built request entity
|
||||
*/
|
||||
MockServerHttpRequest body(Publisher<? extends DataBuffer> body);
|
||||
|
||||
/**
|
||||
* Set the body of the request and build it.
|
||||
* <p>The String is assumed to be UTF-8 encoded unless the request has a
|
||||
* "content-type" header with a charset attribute.
|
||||
* @param body the body as text
|
||||
* @return the built request entity
|
||||
*/
|
||||
MockServerHttpRequest body(String body);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static class DefaultBodyBuilder implements BodyBuilder {
|
||||
|
||||
private final HttpMethod method;
|
||||
|
||||
private final URI url;
|
||||
|
||||
private String contextPath;
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private final MultiValueMap<String, HttpCookie> cookies = new LinkedMultiValueMap<>();
|
||||
|
||||
|
||||
public DefaultBodyBuilder(HttpMethod method, URI url) {
|
||||
this.method = method;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder contextPath(String contextPath) {
|
||||
this.contextPath = contextPath;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder cookie(String path, HttpCookie... cookies) {
|
||||
this.cookies.put(path, Arrays.asList(cookies));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder header(String headerName, String... headerValues) {
|
||||
for (String headerValue : headerValues) {
|
||||
this.headers.add(headerName, headerValue);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder accept(MediaType... acceptableMediaTypes) {
|
||||
this.headers.setAccept(Arrays.asList(acceptableMediaTypes));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder acceptCharset(Charset... acceptableCharsets) {
|
||||
this.headers.setAcceptCharset(Arrays.asList(acceptableCharsets));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder contentLength(long contentLength) {
|
||||
this.headers.setContentLength(contentLength);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder contentType(MediaType contentType) {
|
||||
this.headers.setContentType(contentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder ifModifiedSince(long ifModifiedSince) {
|
||||
this.headers.setIfModifiedSince(ifModifiedSince);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder ifUnmodifiedSince(long ifUnmodifiedSince) {
|
||||
this.headers.setIfUnmodifiedSince(ifUnmodifiedSince);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder ifNoneMatch(String... ifNoneMatches) {
|
||||
this.headers.setIfNoneMatch(Arrays.asList(ifNoneMatches));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodyBuilder range(HttpRange... ranges) {
|
||||
this.headers.setRange(Arrays.asList(ranges));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerHttpRequest body(Publisher<? extends DataBuffer> body) {
|
||||
return new MockServerHttpRequest(this.method, this.url, this.contextPath,
|
||||
this.headers, this.cookies, body);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerHttpRequest body(String body) {
|
||||
Charset charset = getCharset();
|
||||
byte[] bytes = body.getBytes(charset);
|
||||
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
|
||||
DataBuffer buffer = new DefaultDataBufferFactory().wrap(byteBuffer);
|
||||
return body(Flux.just(buffer));
|
||||
}
|
||||
|
||||
private Charset getCharset() {
|
||||
MediaType contentType = this.headers.getContentType();
|
||||
Charset charset = (contentType != null ? contentType.getCharset() : null);
|
||||
charset = charset != null ? charset : StandardCharsets.UTF_8;
|
||||
return charset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MockServerHttpRequest build() {
|
||||
return body(Flux.empty());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,127 +18,61 @@ package org.springframework.mock.http.server.reactive.test;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.reactivestreams.Publisher;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
|
||||
import org.springframework.core.io.buffer.support.DataBufferTestUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.http.server.reactive.AbstractServerHttpResponse;
|
||||
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Mock implementation of {@link ServerHttpResponse}.
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 5.0
|
||||
*/
|
||||
public class MockServerHttpResponse implements ServerHttpResponse {
|
||||
|
||||
private HttpStatus status;
|
||||
|
||||
private final HttpHeaders headers = new HttpHeaders();
|
||||
|
||||
private final MultiValueMap<String, ResponseCookie> cookies = new LinkedMultiValueMap<>();
|
||||
|
||||
private Function<String, String> urlEncoder = url -> url;
|
||||
public class MockServerHttpResponse extends AbstractServerHttpResponse {
|
||||
|
||||
private Flux<DataBuffer> body;
|
||||
|
||||
private Flux<Publisher<DataBuffer>> bodyWithFlushes;
|
||||
|
||||
private DataBufferFactory bufferFactory = new DefaultDataBufferFactory();
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setStatusCode(HttpStatus status) {
|
||||
this.status = status;
|
||||
return true;
|
||||
public MockServerHttpResponse() {
|
||||
super(new DefaultDataBufferFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpStatus getStatusCode() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpHeaders getHeaders() {
|
||||
return this.headers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiValueMap<String, ResponseCookie> getCookies() {
|
||||
return this.cookies;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String encodeUrl(String url) {
|
||||
return (this.urlEncoder != null ? this.urlEncoder.apply(url) : url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerUrlEncoder(Function<String, String> encoder) {
|
||||
this.urlEncoder = (this.urlEncoder != null ? this.urlEncoder.andThen(encoder) : encoder);
|
||||
}
|
||||
|
||||
public Publisher<DataBuffer> getBody() {
|
||||
/**
|
||||
* Return the output Publisher used to write to the response.
|
||||
*/
|
||||
public Flux<DataBuffer> getBody() {
|
||||
return this.body;
|
||||
}
|
||||
|
||||
public Publisher<Publisher<DataBuffer>> getBodyWithFlush() {
|
||||
return this.bodyWithFlushes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
|
||||
this.body = Flux.from(body);
|
||||
return this.body.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
|
||||
this.bodyWithFlushes = Flux.from(body).map(Flux::from);
|
||||
return this.bodyWithFlushes.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCommit(Supplier<? extends Mono<Void>> action) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> setComplete() {
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataBufferFactory bufferFactory() {
|
||||
return this.bufferFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the body of the response aggregated and converted to a String
|
||||
* using the charset of the Content-Type response or otherwise defaulting
|
||||
* to "UTF-8".
|
||||
* Return the response body aggregated and converted to a String using the
|
||||
* charset of the Content-Type response or otherwise as "UTF-8".
|
||||
*/
|
||||
public Mono<String> getBodyAsString() {
|
||||
Charset charset = getCharset();
|
||||
return Flux.from(getBody())
|
||||
return getBody()
|
||||
.reduce(bufferFactory().allocateBuffer(), (previous, current) -> {
|
||||
previous.write(current);
|
||||
DataBufferUtils.release(current);
|
||||
return previous;
|
||||
})
|
||||
.map(buffer -> DataBufferTestUtils.dumpString(buffer, charset));
|
||||
.map(buffer -> bufferToString(buffer, charset));
|
||||
}
|
||||
|
||||
private static String bufferToString(DataBuffer buffer, Charset charset) {
|
||||
Assert.notNull(charset, "'charset' must not be null");
|
||||
byte[] bytes = new byte[buffer.readableByteCount()];
|
||||
buffer.read(bytes);
|
||||
return new String(bytes, charset);
|
||||
}
|
||||
|
||||
private Charset getCharset() {
|
||||
@@ -150,4 +84,27 @@ public class MockServerHttpResponse implements ServerHttpResponse {
|
||||
return (charset != null ? charset : StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Void> writeWithInternal(Publisher<? extends DataBuffer> body) {
|
||||
this.body = Flux.from(body);
|
||||
return Mono.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Mono<Void> writeAndFlushWithInternal(Publisher<? extends Publisher<? extends DataBuffer>> body) {
|
||||
return writeWithInternal(Flux.from(body).flatMap(Flux::from));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyStatusCode() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyHeaders() {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void applyCookies() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.DefaultWebSessionManager;
|
||||
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -51,17 +50,12 @@ public class WebExchangeDataBinderTests {
|
||||
|
||||
private TestBean testBean;
|
||||
|
||||
private MockServerHttpRequest request;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.testBean = new TestBean();
|
||||
this.binder = new WebExchangeDataBinder(this.testBean, "person");
|
||||
this.binder.registerCustomEditor(ITestBean.class, new TestBeanPropertyEditor());
|
||||
|
||||
this.request = new MockServerHttpRequest();
|
||||
this.request.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
}
|
||||
|
||||
|
||||
@@ -70,8 +64,7 @@ public class WebExchangeDataBinderTests {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("spouse", "someValue");
|
||||
formData.add("spouse.name", "test");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
|
||||
assertNotNull(this.testBean.getSpouse());
|
||||
assertEquals("test", testBean.getSpouse().getName());
|
||||
@@ -82,13 +75,11 @@ public class WebExchangeDataBinderTests {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("_postProcessed", "visible");
|
||||
formData.add("postProcessed", "on");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertTrue(this.testBean.isPostProcessed());
|
||||
|
||||
formData.remove("postProcessed");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertFalse(this.testBean.isPostProcessed());
|
||||
}
|
||||
|
||||
@@ -99,13 +90,11 @@ public class WebExchangeDataBinderTests {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("_postProcessed", "visible");
|
||||
formData.add("postProcessed", "on");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertTrue(this.testBean.isPostProcessed());
|
||||
|
||||
formData.remove("postProcessed");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertFalse(this.testBean.isPostProcessed());
|
||||
}
|
||||
|
||||
@@ -114,13 +103,11 @@ public class WebExchangeDataBinderTests {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("!postProcessed", "off");
|
||||
formData.add("postProcessed", "on");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertTrue(this.testBean.isPostProcessed());
|
||||
|
||||
formData.remove("postProcessed");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertFalse(this.testBean.isPostProcessed());
|
||||
}
|
||||
|
||||
@@ -130,18 +117,15 @@ public class WebExchangeDataBinderTests {
|
||||
formData.add("!postProcessed", "on");
|
||||
formData.add("_postProcessed", "visible");
|
||||
formData.add("postProcessed", "on");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertTrue(this.testBean.isPostProcessed());
|
||||
|
||||
formData.remove("postProcessed");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertTrue(this.testBean.isPostProcessed());
|
||||
|
||||
formData.remove("!postProcessed");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertFalse(this.testBean.isPostProcessed());
|
||||
}
|
||||
|
||||
@@ -150,13 +134,11 @@ public class WebExchangeDataBinderTests {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("!name", "anonymous");
|
||||
formData.add("name", "Scott");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertEquals("Scott", this.testBean.getName());
|
||||
|
||||
formData.remove("name");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertEquals("anonymous", this.testBean.getName());
|
||||
}
|
||||
|
||||
@@ -166,14 +148,12 @@ public class WebExchangeDataBinderTests {
|
||||
formData.add("stringArray", "bar");
|
||||
formData.add("stringArray", "abc");
|
||||
formData.add("stringArray", "123,def");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertEquals("Expected all three items to be bound", 3, this.testBean.getStringArray().length);
|
||||
|
||||
formData.remove("stringArray");
|
||||
formData.add("stringArray", "123,def");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
assertEquals("Expected only 1 item to be bound", 1, this.testBean.getStringArray().length);
|
||||
}
|
||||
|
||||
@@ -182,8 +162,7 @@ public class WebExchangeDataBinderTests {
|
||||
MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("spouse.name", "test");
|
||||
formData.add("spouse", "someValue");
|
||||
this.request.setBody(generateForm(formData));
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
this.binder.bind(exchange(formData)).blockMillis(5000);
|
||||
|
||||
assertNotNull(this.testBean.getSpouse());
|
||||
assertEquals("test", this.testBean.getSpouse().getName());
|
||||
@@ -191,10 +170,10 @@ public class WebExchangeDataBinderTests {
|
||||
|
||||
@Test
|
||||
public void testBindingWithQueryParams() throws Exception {
|
||||
MultiValueMap<String, String> queryParams = createExchange().getRequest().getQueryParams();
|
||||
queryParams.add("spouse", "someValue");
|
||||
queryParams.add("spouse.name", "test");
|
||||
this.binder.bind(createExchange()).blockMillis(5000);
|
||||
String url = "/path?spouse=someValue&spouse.name=test";
|
||||
MockServerHttpRequest request = MockServerHttpRequest.post(url).build();
|
||||
ServerWebExchange exchange = new DefaultServerWebExchange(request, new MockServerHttpResponse());
|
||||
this.binder.bind(exchange).blockMillis(5000);
|
||||
|
||||
assertNotNull(this.testBean.getSpouse());
|
||||
assertEquals("test", this.testBean.getSpouse().getName());
|
||||
@@ -227,9 +206,14 @@ public class WebExchangeDataBinderTests {
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
private ServerWebExchange createExchange() {
|
||||
return new DefaultServerWebExchange(
|
||||
this.request, new MockServerHttpResponse(), new DefaultWebSessionManager());
|
||||
private ServerWebExchange exchange(MultiValueMap<String, String> formData) {
|
||||
|
||||
MockServerHttpRequest request = MockServerHttpRequest
|
||||
.post("/")
|
||||
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
.body(generateForm(formData));
|
||||
|
||||
return new DefaultServerWebExchange(request, new MockServerHttpResponse());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,57 +16,53 @@
|
||||
|
||||
package org.springframework.web.cors.reactive;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.web.cors.reactive.CorsUtils;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.get;
|
||||
import static org.springframework.mock.http.server.reactive.test.MockServerHttpRequest.options;
|
||||
|
||||
/**
|
||||
* Test case for reactive {@link CorsUtils}.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class CorsUtilsTests {
|
||||
|
||||
@Test
|
||||
public void isCorsRequest() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.addHeader(HttpHeaders.ORIGIN, "http://domain.com");
|
||||
MockServerHttpRequest request = get("/").header(HttpHeaders.ORIGIN, "http://domain.com").build();
|
||||
assertTrue(CorsUtils.isCorsRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotCorsRequest() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
MockServerHttpRequest request = get("/").build();
|
||||
assertFalse(CorsUtils.isCorsRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isPreFlightRequest() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
request.addHeader(HttpHeaders.ORIGIN, "http://domain.com");
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
MockServerHttpRequest request = options("/")
|
||||
.header(HttpHeaders.ORIGIN, "http://domain.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.build();
|
||||
assertTrue(CorsUtils.isPreFlightRequest(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotPreFlightRequest() {
|
||||
MockServerHttpRequest request = new MockServerHttpRequest();
|
||||
MockServerHttpRequest request = get("/").build();
|
||||
assertFalse(CorsUtils.isPreFlightRequest(request));
|
||||
|
||||
request = new MockServerHttpRequest();
|
||||
request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
request.addHeader(HttpHeaders.ORIGIN, "http://domain.com");
|
||||
request = options("/").header(HttpHeaders.ORIGIN, "http://domain.com").build();
|
||||
assertFalse(CorsUtils.isPreFlightRequest(request));
|
||||
|
||||
request = new MockServerHttpRequest();
|
||||
request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
request = options("/").header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "GET").build();
|
||||
assertFalse(CorsUtils.isPreFlightRequest(request));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.web.cors.reactive;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -25,9 +26,7 @@ import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -45,11 +44,9 @@ import static org.springframework.http.HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD
|
||||
public class DefaultCorsProcessorTests {
|
||||
|
||||
private MockServerHttpRequest request;
|
||||
|
||||
|
||||
private MockServerHttpResponse response;
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
private DefaultCorsProcessor processor;
|
||||
|
||||
private CorsConfiguration conf;
|
||||
@@ -57,43 +54,35 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
this.request = new MockServerHttpRequest();
|
||||
this.request.setUri("http://localhost/test.html");
|
||||
this.conf = new CorsConfiguration();
|
||||
this.response = new MockServerHttpResponse();
|
||||
this.response.setStatusCode(HttpStatus.OK);
|
||||
this.processor = new DefaultCorsProcessor();
|
||||
this.exchange = new DefaultServerWebExchange(this.request, this.response, new MockWebSessionManager());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void actualRequestWithOriginHeader() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.request = actualRequest().build();
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actualRequestWithOriginHeaderAndNullConfig() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
|
||||
this.processor.processRequest(null, this.exchange);
|
||||
this.request = actualRequest().build();
|
||||
this.processor.processRequest(null, createExchange());
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.OK, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actualRequestWithOriginHeaderAndAllowedOrigin() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request = actualRequest().build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("*", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertFalse(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_MAX_AGE));
|
||||
@@ -103,14 +92,13 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void actualRequestCredentials() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request = actualRequest().build();
|
||||
this.conf.addAllowedOrigin("http://domain1.com");
|
||||
this.conf.addAllowedOrigin("http://domain2.com");
|
||||
this.conf.addAllowedOrigin("http://domain3.com");
|
||||
this.conf.setAllowCredentials(true);
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
@@ -120,12 +108,11 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void actualRequestCredentialsWithOriginWildcard() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request = actualRequest().build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
this.conf.setAllowCredentials(true);
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
@@ -135,24 +122,22 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void actualRequestCaseInsensitiveOriginMatch() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request = actualRequest().build();
|
||||
this.conf.addAllowedOrigin("http://DOMAIN2.com");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.OK, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void actualRequestExposedHeaders() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.GET);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request = actualRequest().build();
|
||||
this.conf.addExposedHeader("header1");
|
||||
this.conf.addExposedHeader("header2");
|
||||
this.conf.addAllowedOrigin("http://domain2.com");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS));
|
||||
@@ -163,84 +148,76 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestAllOriginsAllowed() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "GET").build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertEquals(HttpStatus.OK, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void preflightRequestWrongAllowedMethod() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "DELETE");
|
||||
this.request = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "DELETE").build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preflightRequestMatchedAllowedMethod() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request = preFlightRequest().header(ACCESS_CONTROL_REQUEST_METHOD, "GET").build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertEquals(HttpStatus.OK, this.response.getStatusCode());
|
||||
assertEquals("GET,HEAD", this.response.getHeaders().getFirst(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preflightRequestTestWithOriginButWithoutOtherHeaders() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request = preFlightRequest().build();
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preflightRequestWithoutRequestMethod() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
|
||||
this.request = preFlightRequest().header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1").build();
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preflightRequestWithRequestAndMethodHeaderButNoConfig() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
|
||||
.build();
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void preflightRequestValidRequestAndConfig() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
|
||||
.build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
this.conf.addAllowedMethod("GET");
|
||||
this.conf.addAllowedMethod("PUT");
|
||||
this.conf.addAllowedHeader("header1");
|
||||
this.conf.addAllowedHeader("header2");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("*", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS));
|
||||
@@ -251,17 +228,17 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestCredentials() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
|
||||
.build();
|
||||
this.conf.addAllowedOrigin("http://domain1.com");
|
||||
this.conf.addAllowedOrigin("http://domain2.com");
|
||||
this.conf.addAllowedOrigin("http://domain3.com");
|
||||
this.conf.addAllowedHeader("Header1");
|
||||
this.conf.setAllowCredentials(true);
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS));
|
||||
@@ -271,17 +248,17 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestCredentialsWithOriginWildcard() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1")
|
||||
.build();
|
||||
this.conf.addAllowedOrigin("http://domain1.com");
|
||||
this.conf.addAllowedOrigin("*");
|
||||
this.conf.addAllowedOrigin("http://domain3.com");
|
||||
this.conf.addAllowedHeader("Header1");
|
||||
this.conf.setAllowCredentials(true);
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals("http://domain2.com", this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.OK, this.response.getStatusCode());
|
||||
@@ -289,16 +266,16 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestAllowedHeaders() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2")
|
||||
.build();
|
||||
this.conf.addAllowedHeader("Header1");
|
||||
this.conf.addAllowedHeader("Header2");
|
||||
this.conf.addAllowedHeader("Header3");
|
||||
this.conf.addAllowedOrigin("http://domain2.com");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
|
||||
assertTrue(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
|
||||
@@ -309,14 +286,14 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestAllowsAllHeaders() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "Header1, Header2")
|
||||
.build();
|
||||
this.conf.addAllowedHeader("*");
|
||||
this.conf.addAllowedOrigin("http://domain2.com");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
|
||||
assertTrue(this.response.getHeaders().getFirst(ACCESS_CONTROL_ALLOW_HEADERS).contains("Header1"));
|
||||
@@ -327,14 +304,14 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestWithEmptyHeaders() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_HEADERS, "");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.header(ACCESS_CONTROL_REQUEST_HEADERS, "")
|
||||
.build();
|
||||
this.conf.addAllowedHeader("*");
|
||||
this.conf.addAllowedOrigin("http://domain2.com");
|
||||
|
||||
this.processor.processRequest(this.conf, this.exchange);
|
||||
this.processor.processRequest(this.conf, createExchange());
|
||||
assertTrue(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_HEADERS));
|
||||
assertEquals(HttpStatus.OK, this.response.getStatusCode());
|
||||
@@ -342,14 +319,33 @@ public class DefaultCorsProcessorTests {
|
||||
|
||||
@Test
|
||||
public void preflightRequestWithNullConfig() throws Exception {
|
||||
this.request.setHttpMethod(HttpMethod.OPTIONS);
|
||||
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
this.request.addHeader(ACCESS_CONTROL_REQUEST_METHOD, "GET");
|
||||
this.request = preFlightRequest()
|
||||
.header(ACCESS_CONTROL_REQUEST_METHOD, "GET")
|
||||
.build();
|
||||
this.conf.addAllowedOrigin("*");
|
||||
|
||||
this.processor.processRequest(null, this.exchange);
|
||||
this.processor.processRequest(null, createExchange());
|
||||
assertFalse(this.response.getHeaders().containsKey(ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
assertEquals(HttpStatus.FORBIDDEN, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
private MockServerHttpRequest.BaseBuilder<?> actualRequest() {
|
||||
return corsRequest(HttpMethod.GET);
|
||||
}
|
||||
|
||||
private MockServerHttpRequest.BaseBuilder<?> preFlightRequest() {
|
||||
return corsRequest(HttpMethod.OPTIONS);
|
||||
}
|
||||
|
||||
private MockServerHttpRequest.BaseBuilder<?> corsRequest(HttpMethod httpMethod) {
|
||||
return MockServerHttpRequest
|
||||
.method(httpMethod, "http://localhost/test.html")
|
||||
.header(HttpHeaders.ORIGIN, "http://domain2.com");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DefaultServerWebExchange createExchange() {
|
||||
return new DefaultServerWebExchange(this.request, this.response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,6 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
@@ -64,12 +63,10 @@ public class UrlBasedCorsConfigurationSourceTests {
|
||||
this.configSource.getCorsConfigurations().put("/**", new CorsConfiguration());
|
||||
}
|
||||
|
||||
|
||||
private ServerWebExchange createExchange(HttpMethod httpMethod, String url) {
|
||||
ServerHttpRequest request = new MockServerHttpRequest(httpMethod, url);
|
||||
ServerHttpRequest request = MockServerHttpRequest.method(httpMethod, url).build();
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
MockWebSessionManager sessionManager = new MockWebSessionManager();
|
||||
return new DefaultServerWebExchange(request, response, sessionManager);
|
||||
return new DefaultServerWebExchange(request, response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -35,7 +36,6 @@ import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -57,9 +57,7 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
|
||||
private MockServerHttpRequest request;
|
||||
|
||||
private MockServerHttpResponse response;
|
||||
|
||||
private DefaultServerWebExchange exchange;
|
||||
private MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
|
||||
private Instant currentDate;
|
||||
|
||||
@@ -77,20 +75,18 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
|
||||
@Before
|
||||
public void setUp() throws URISyntaxException {
|
||||
currentDate = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
|
||||
dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
request = new MockServerHttpRequest(method, "http://example.org");
|
||||
response = new MockServerHttpResponse();
|
||||
exchange = new DefaultServerWebExchange(request, response, new MockWebSessionManager());
|
||||
this.currentDate = Instant.now().truncatedTo(ChronoUnit.SECONDS);
|
||||
this.dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
|
||||
this.dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedNon2xxStatus() {
|
||||
request.getHeaders().setIfModifiedSince(this.currentDate.toEpochMilli());
|
||||
response.setStatusCode(HttpStatus.NOT_MODIFIED);
|
||||
this.request = request().ifModifiedSince(this.currentDate.toEpochMilli()).build();
|
||||
this.response.setStatusCode(HttpStatus.NOT_MODIFIED);
|
||||
|
||||
assertFalse(exchange.checkNotModified(this.currentDate));
|
||||
assertFalse(createExchange().checkNotModified(this.currentDate));
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(-1, response.getHeaders().getLastModified());
|
||||
}
|
||||
@@ -98,18 +94,18 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test // SPR-14559
|
||||
public void checkNotModifiedInvalidIfNoneMatchHeader() {
|
||||
String eTag = "\"etagvalue\"";
|
||||
request.getHeaders().setIfNoneMatch("missingquotes");
|
||||
assertFalse(exchange.checkNotModified(eTag));
|
||||
this.request = request().ifNoneMatch("missingquotes").build();
|
||||
assertFalse(createExchange().checkNotModified(eTag));
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedHeaderAlreadySet() {
|
||||
request.getHeaders().setIfModifiedSince(currentDate.toEpochMilli());
|
||||
response.getHeaders().add("Last-Modified", CURRENT_TIME);
|
||||
this.request = request().ifModifiedSince(currentDate.toEpochMilli()).build();
|
||||
this.response.getHeaders().add("Last-Modified", CURRENT_TIME);
|
||||
|
||||
assertTrue(exchange.checkNotModified(currentDate));
|
||||
assertTrue(createExchange().checkNotModified(currentDate));
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(1, response.getHeaders().get("Last-Modified").size());
|
||||
assertEquals(CURRENT_TIME, response.getHeaders().getFirst("Last-Modified"));
|
||||
@@ -117,9 +113,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
|
||||
@Test
|
||||
public void checkNotModifiedTimestamp() throws Exception {
|
||||
request.getHeaders().setIfModifiedSince(currentDate.toEpochMilli());
|
||||
this.request = request().ifModifiedSince(currentDate.toEpochMilli()).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(currentDate));
|
||||
assertTrue(createExchange().checkNotModified(currentDate));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(currentDate.toEpochMilli(), response.getHeaders().getLastModified());
|
||||
@@ -128,9 +124,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkModifiedTimestamp() {
|
||||
Instant oneMinuteAgo = currentDate.minusSeconds(60);
|
||||
request.getHeaders().setIfModifiedSince(oneMinuteAgo.toEpochMilli());
|
||||
this.request = request().ifModifiedSince(oneMinuteAgo.toEpochMilli()).build();
|
||||
|
||||
assertFalse(exchange.checkNotModified(currentDate));
|
||||
assertFalse(createExchange().checkNotModified(currentDate));
|
||||
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(currentDate.toEpochMilli(), response.getHeaders().getLastModified());
|
||||
@@ -139,9 +135,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedETag() {
|
||||
String eTag = "\"Foo\"";
|
||||
request.getHeaders().setIfNoneMatch(eTag);
|
||||
this.request = request().ifNoneMatch(eTag).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag));
|
||||
assertTrue(createExchange().checkNotModified(eTag));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -150,9 +146,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedETagWithSeparatorChars() {
|
||||
String eTag = "\"Foo, Bar\"";
|
||||
request.getHeaders().setIfNoneMatch(eTag);
|
||||
this.request = request().ifNoneMatch(eTag).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag));
|
||||
assertTrue(createExchange().checkNotModified(eTag));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -163,9 +159,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
public void checkModifiedETag() {
|
||||
String currentETag = "\"Foo\"";
|
||||
String oldEtag = "Bar";
|
||||
request.getHeaders().setIfNoneMatch(oldEtag);
|
||||
this.request = request().ifNoneMatch(oldEtag).build();
|
||||
|
||||
assertFalse(exchange.checkNotModified(currentETag));
|
||||
assertFalse(createExchange().checkNotModified(currentETag));
|
||||
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(currentETag, response.getHeaders().getETag());
|
||||
@@ -175,9 +171,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
public void checkNotModifiedUnpaddedETag() {
|
||||
String eTag = "Foo";
|
||||
String paddedEtag = String.format("\"%s\"", eTag);
|
||||
request.getHeaders().setIfNoneMatch(paddedEtag);
|
||||
this.request = request().ifNoneMatch(paddedEtag).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag));
|
||||
assertTrue(createExchange().checkNotModified(eTag));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(paddedEtag, response.getHeaders().getETag());
|
||||
@@ -187,9 +183,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
public void checkModifiedUnpaddedETag() {
|
||||
String currentETag = "Foo";
|
||||
String oldEtag = "Bar";
|
||||
request.getHeaders().setIfNoneMatch(oldEtag);
|
||||
this.request = request().ifNoneMatch(oldEtag).build();
|
||||
|
||||
assertFalse(exchange.checkNotModified(currentETag));
|
||||
assertFalse(createExchange().checkNotModified(currentETag));
|
||||
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(String.format("\"%s\"", currentETag), response.getHeaders().getETag());
|
||||
@@ -198,9 +194,8 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedWildcardIsIgnored() {
|
||||
String eTag = "\"Foo\"";
|
||||
request.getHeaders().setIfNoneMatch("*");
|
||||
|
||||
assertFalse(exchange.checkNotModified(eTag));
|
||||
this.request = request().ifNoneMatch("*").build();
|
||||
assertFalse(createExchange().checkNotModified(eTag));
|
||||
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -209,10 +204,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedETagAndTimestamp() {
|
||||
String eTag = "\"Foo\"";
|
||||
request.getHeaders().setIfNoneMatch(eTag);
|
||||
request.getHeaders().setIfModifiedSince(currentDate.toEpochMilli());
|
||||
this.request = request().ifNoneMatch(eTag).ifModifiedSince(currentDate.toEpochMilli()).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag, currentDate));
|
||||
assertTrue(createExchange().checkNotModified(eTag, currentDate));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -223,11 +217,10 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedETagAndModifiedTimestamp() {
|
||||
String eTag = "\"Foo\"";
|
||||
request.getHeaders().setIfNoneMatch(eTag);
|
||||
Instant oneMinuteAgo = currentDate.minusSeconds(60);
|
||||
request.getHeaders().setIfModifiedSince(oneMinuteAgo.toEpochMilli());
|
||||
this.request = request().ifNoneMatch(eTag).ifModifiedSince(oneMinuteAgo.toEpochMilli()).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag, currentDate));
|
||||
assertTrue(createExchange().checkNotModified(eTag, currentDate));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -238,10 +231,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
public void checkModifiedETagAndNotModifiedTimestamp() throws Exception {
|
||||
String currentETag = "\"Foo\"";
|
||||
String oldEtag = "\"Bar\"";
|
||||
request.getHeaders().setIfNoneMatch(oldEtag);
|
||||
request.getHeaders().setIfModifiedSince(currentDate.toEpochMilli());
|
||||
this.request = request().ifNoneMatch(oldEtag).ifModifiedSince(currentDate.toEpochMilli()).build();
|
||||
|
||||
assertFalse(exchange.checkNotModified(currentETag, currentDate));
|
||||
assertFalse(createExchange().checkNotModified(currentETag, currentDate));
|
||||
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(currentETag, response.getHeaders().getETag());
|
||||
@@ -252,9 +244,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
public void checkNotModifiedETagWeakStrong() {
|
||||
String eTag = "\"Foo\"";
|
||||
String weakEtag = String.format("W/%s", eTag);
|
||||
request.getHeaders().setIfNoneMatch(eTag);
|
||||
this.request = request().ifNoneMatch(eTag).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(weakEtag));
|
||||
assertTrue(createExchange().checkNotModified(weakEtag));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(weakEtag, response.getHeaders().getETag());
|
||||
@@ -263,9 +255,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedETagStrongWeak() {
|
||||
String eTag = "\"Foo\"";
|
||||
request.getHeaders().setIfNoneMatch(String.format("W/%s", eTag));
|
||||
this.request = request().ifNoneMatch(String.format("W/%s", eTag)).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag));
|
||||
assertTrue(createExchange().checkNotModified(eTag));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -275,9 +267,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
public void checkNotModifiedMultipleETags() {
|
||||
String eTag = "\"Bar\"";
|
||||
String multipleETags = String.format("\"Foo\", %s", eTag);
|
||||
request.getHeaders().setIfNoneMatch(multipleETags);
|
||||
this.request = request().ifNoneMatch(multipleETags).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(eTag));
|
||||
assertTrue(createExchange().checkNotModified(eTag));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(eTag, response.getHeaders().getETag());
|
||||
@@ -286,10 +278,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedTimestampWithLengthPart() throws Exception {
|
||||
long epochTime = dateFormat.parse(CURRENT_TIME).getTime();
|
||||
request.setHttpMethod(HttpMethod.GET);
|
||||
request.setHeader("If-Modified-Since", "Wed, 09 Apr 2014 09:57:42 GMT; length=13774");
|
||||
this.request = request().header("If-Modified-Since", "Wed, 09 Apr 2014 09:57:42 GMT; length=13774").build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(Instant.ofEpochMilli(epochTime)));
|
||||
assertTrue(createExchange().checkNotModified(Instant.ofEpochMilli(epochTime)));
|
||||
|
||||
assertEquals(304, response.getStatusCode().value());
|
||||
assertEquals(epochTime, response.getHeaders().getLastModified());
|
||||
@@ -298,10 +289,9 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkModifiedTimestampWithLengthPart() throws Exception {
|
||||
long epochTime = dateFormat.parse(CURRENT_TIME).getTime();
|
||||
request.setHttpMethod(HttpMethod.GET);
|
||||
request.setHeader("If-Modified-Since", "Tue, 08 Apr 2014 09:57:42 GMT; length=13774");
|
||||
this.request = request().header("If-Modified-Since", "Tue, 08 Apr 2014 09:57:42 GMT; length=13774").build();
|
||||
|
||||
assertFalse(exchange.checkNotModified(Instant.ofEpochMilli(epochTime)));
|
||||
assertFalse(createExchange().checkNotModified(Instant.ofEpochMilli(epochTime)));
|
||||
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(epochTime, response.getHeaders().getLastModified());
|
||||
@@ -310,10 +300,10 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedTimestampConditionalPut() throws Exception {
|
||||
Instant oneMinuteAgo = currentDate.minusSeconds(60);
|
||||
request.setHttpMethod(HttpMethod.PUT);
|
||||
request.getHeaders().setIfUnmodifiedSince(currentDate.toEpochMilli());
|
||||
long millis = currentDate.toEpochMilli();
|
||||
this.request = MockServerHttpRequest.put("http://example.org").ifUnmodifiedSince(millis).build();
|
||||
|
||||
assertFalse(exchange.checkNotModified(oneMinuteAgo));
|
||||
assertFalse(createExchange().checkNotModified(oneMinuteAgo));
|
||||
assertNull(response.getStatusCode());
|
||||
assertEquals(-1, response.getHeaders().getLastModified());
|
||||
}
|
||||
@@ -321,12 +311,22 @@ public class DefaultServerWebExchangeCheckNotModifiedTests {
|
||||
@Test
|
||||
public void checkNotModifiedTimestampConditionalPutConflict() throws Exception {
|
||||
Instant oneMinuteAgo = currentDate.minusSeconds(60);
|
||||
request.setHttpMethod(HttpMethod.PUT);
|
||||
request.getHeaders().setIfUnmodifiedSince(oneMinuteAgo.toEpochMilli());
|
||||
long millis = oneMinuteAgo.toEpochMilli();
|
||||
this.request = MockServerHttpRequest.put("http://example.org").ifUnmodifiedSince(millis).build();
|
||||
|
||||
assertTrue(exchange.checkNotModified(currentDate));
|
||||
assertTrue(createExchange().checkNotModified(currentDate));
|
||||
assertEquals(412, response.getStatusCode().value());
|
||||
assertEquals(-1, response.getHeaders().getLastModified());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private MockServerHttpRequest.BaseBuilder<?> request() {
|
||||
return MockServerHttpRequest.get("http://example.org");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private DefaultServerWebExchange createExchange() {
|
||||
return new DefaultServerWebExchange(this.request, this.response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
@@ -28,8 +27,6 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebExceptionHandler;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
import org.springframework.web.server.session.WebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -48,10 +45,9 @@ public class ExceptionHandlingHttpHandlerTests {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
WebSessionManager sessionManager = new MockWebSessionManager();
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "http://localhost:8080");
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("http://localhost:8080").build();
|
||||
this.response = new MockServerHttpResponse();
|
||||
this.exchange = new DefaultServerWebExchange(request, this.response, sessionManager);
|
||||
this.exchange = new DefaultServerWebExchange(request, this.response);
|
||||
this.targetHandler = new StubWebHandler(new IllegalStateException("boo"));
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
@@ -34,7 +33,10 @@ import org.springframework.web.server.WebFilterChain;
|
||||
import org.springframework.web.server.WebHandler;
|
||||
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Rossen Stoyanchev
|
||||
@@ -50,7 +52,7 @@ public class FilteringWebHandlerTests {
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.request = new MockServerHttpRequest(HttpMethod.GET, "http://localhost");
|
||||
this.request = MockServerHttpRequest.get("http://localhost").build();
|
||||
this.response = new MockServerHttpResponse();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,19 +18,17 @@ package org.springframework.web.server.handler;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.test.StepVerifier;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.server.ResponseStatusException;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.DefaultServerWebExchange;
|
||||
import org.springframework.web.server.session.MockWebSessionManager;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
@@ -44,37 +42,36 @@ public class ResponseStatusExceptionHandlerTests {
|
||||
|
||||
private ResponseStatusExceptionHandler handler;
|
||||
|
||||
private MockServerHttpResponse response;
|
||||
private MockServerHttpRequest request;
|
||||
|
||||
private ServerWebExchange exchange;
|
||||
private MockServerHttpResponse response;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.handler = new ResponseStatusExceptionHandler();
|
||||
this.request = MockServerHttpRequest.get("/").build();
|
||||
this.response = new MockServerHttpResponse();
|
||||
this.exchange = new DefaultServerWebExchange(
|
||||
new MockServerHttpRequest(HttpMethod.GET, "/path"), this.response,
|
||||
new MockWebSessionManager());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void handleException() throws Exception {
|
||||
Throwable ex = new ResponseStatusException(HttpStatus.BAD_REQUEST, "");
|
||||
this.handler.handle(this.exchange, ex).block(Duration.ofSeconds(5));
|
||||
|
||||
this.handler.handle(createExchange(), ex).block(Duration.ofSeconds(5));
|
||||
assertEquals(HttpStatus.BAD_REQUEST, this.response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unresolvedException() throws Exception {
|
||||
Throwable expected = new IllegalStateException();
|
||||
Mono<Void> mono = this.handler.handle(this.exchange, expected);
|
||||
Mono<Void> mono = this.handler.handle(createExchange(), expected);
|
||||
StepVerifier.create(mono).consumeErrorWith(actual -> assertSame(expected, actual)).verify();
|
||||
}
|
||||
|
||||
StepVerifier.create(mono)
|
||||
.consumeErrorWith(actual -> assertSame(expected, actual))
|
||||
.verify();
|
||||
@NotNull
|
||||
private DefaultServerWebExchange createExchange() {
|
||||
return new DefaultServerWebExchange(this.request, this.response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.List;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest;
|
||||
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
@@ -45,18 +44,20 @@ import static org.junit.Assert.assertSame;
|
||||
*/
|
||||
public class DefaultWebSessionManagerTests {
|
||||
|
||||
private final DefaultWebSessionManager manager = new DefaultWebSessionManager();
|
||||
private DefaultWebSessionManager manager;
|
||||
|
||||
private final TestWebSessionIdResolver idResolver = new TestWebSessionIdResolver();
|
||||
private TestWebSessionIdResolver idResolver;
|
||||
|
||||
private DefaultServerWebExchange exchange;
|
||||
private ServerWebExchange exchange;
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.manager = new DefaultWebSessionManager();
|
||||
this.idResolver = new TestWebSessionIdResolver();
|
||||
this.manager.setSessionIdResolver(this.idResolver);
|
||||
|
||||
MockServerHttpRequest request = new MockServerHttpRequest(HttpMethod.GET, "/path");
|
||||
MockServerHttpRequest request = MockServerHttpRequest.get("/path").build();
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
this.exchange = new DefaultServerWebExchange(request, response, this.manager);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user