Polishing
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.web.reactive.function;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
abstract class CastingUtils {
|
||||
|
||||
|
||||
public static <T> HandlerFunction<T> cast(HandlerFunction<?> handlerFunction) {
|
||||
return (HandlerFunction<T>) handlerFunction;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import java.util.Optional;
|
||||
* @param <T> the type of the {@linkplain HandlerFunction handler function} to route to
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.0
|
||||
* @see RoutingFunctions
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface RoutingFunction<T> {
|
||||
@@ -64,9 +65,9 @@ public interface RoutingFunction<T> {
|
||||
default RoutingFunction<?> and(RoutingFunction<?> other) {
|
||||
return request -> {
|
||||
Optional<HandlerFunction<Object>> result = this.route(request).
|
||||
map(CastingUtils::cast);
|
||||
map(RoutingFunctions::cast);
|
||||
return result.isPresent() ? result : other.route(request)
|
||||
.map(CastingUtils::cast);
|
||||
.map(RoutingFunctions::cast);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -28,25 +28,23 @@ import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.adapter.HttpWebHandlerAdapter;
|
||||
|
||||
/**
|
||||
* <strong>Central entry point Spring's functional web framework.</strong>
|
||||
* <strong>Central entry point to Spring's functional web framework.</strong>
|
||||
* Exposes routing functionality, such as to
|
||||
* {@linkplain #route(RequestPredicate, HandlerFunction) create} a {@link RoutingFunction} given a
|
||||
* {@link RequestPredicate} and {@link HandlerFunction}, and to do further
|
||||
* {@linkplain #route(RequestPredicate, HandlerFunction) create} a {@code RoutingFunction} given a
|
||||
* {@code RequestPredicate} and {@code HandlerFunction}, and to do further
|
||||
* {@linkplain #subroute(RequestPredicate, RoutingFunction) subrouting} on an existing routing
|
||||
* function.
|
||||
*
|
||||
* <p>Additionally, this class can {@linkplain #toHttpHandler(RoutingFunction) transform} a
|
||||
* {@link RoutingFunction} into an {@link HttpHandler}, which can be run in
|
||||
* {@linkplain org.springframework.http.server.reactive.ServletHttpHandlerAdapter Servlet 3.1+},
|
||||
* {@linkplain org.springframework.http.server.reactive.ReactorHttpHandlerAdapter Reactor},
|
||||
* {@linkplain org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter RxNetty}, or
|
||||
* {@linkplain org.springframework.http.server.reactive.UndertowHttpHandlerAdapter Undertow}.
|
||||
* Or it {@linkplain #toHandlerMapping(RoutingFunction, Configuration) transform} a
|
||||
* {@link RoutingFunction} into an {@link HandlerMapping}, which can be run in a
|
||||
* {@link org.springframework.web.reactive.DispatcherHandler DispatcherHandler}.
|
||||
* {@code RoutingFunction} into an {@code HttpHandler}, which can be run in Servlet 3.1+,
|
||||
* Reactor, RxNetty, or Undertow.
|
||||
* And it can {@linkplain #toHandlerMapping(RoutingFunction, Configuration) transform} a
|
||||
* {@code RoutingFunction} into an {@code HandlerMapping}, which can be run in a
|
||||
* {@code DispatcherHandler}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 5.0
|
||||
*
|
||||
*/
|
||||
public abstract class RoutingFunctions {
|
||||
|
||||
@@ -57,13 +55,6 @@ public abstract class RoutingFunctions {
|
||||
*/
|
||||
public static final String REQUEST_ATTRIBUTE = RoutingFunctions.class.getName() + ".request";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the
|
||||
* {@linkplain Configuration configuration} used throughout the routing and handling of the
|
||||
* request.
|
||||
*/
|
||||
public static final String CONFIGURATION_ATTRIBUTE = RoutingFunctions.class.getName() + ".configuration";
|
||||
|
||||
/**
|
||||
* Name of the {@link ServerWebExchange} attribute that contains the URI
|
||||
* templates map, mapping variable names to values.
|
||||
@@ -115,10 +106,16 @@ public abstract class RoutingFunctions {
|
||||
* This conversion uses the {@linkplain Configuration#builder() default configuration}.
|
||||
*
|
||||
* <p>The returned {@code HttpHandler} can be adapted to run in
|
||||
* {@linkplain org.springframework.http.server.reactive.ServletHttpHandlerAdapter Servlet 3.1+},
|
||||
* {@linkplain org.springframework.http.server.reactive.ReactorHttpHandlerAdapter Reactor},
|
||||
* {@linkplain org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter RxNetty}, or
|
||||
* {@linkplain org.springframework.http.server.reactive.UndertowHttpHandlerAdapter Undertow}.
|
||||
* <ul>
|
||||
* <li>Servlet 3.1+ using the
|
||||
* {@link org.springframework.http.server.reactive.ServletHttpHandlerAdapter},</li>
|
||||
* <li>Reactor using the
|
||||
* {@link org.springframework.http.server.reactive.ReactorHttpHandlerAdapter},</li>
|
||||
* <li>RxNetty using the
|
||||
* {@link org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter}, or </li>
|
||||
* <li>Undertow using the
|
||||
* {@link org.springframework.http.server.reactive.UndertowHttpHandlerAdapter}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param routingFunction the routing function to convert
|
||||
* @return an http handler that handles HTTP request using the given routing function
|
||||
@@ -132,10 +129,16 @@ public abstract class RoutingFunctions {
|
||||
* using the given configuration.
|
||||
*
|
||||
* <p>The returned {@code HttpHandler} can be adapted to run in
|
||||
* {@linkplain org.springframework.http.server.reactive.ServletHttpHandlerAdapter Servlet 3.1+},
|
||||
* {@linkplain org.springframework.http.server.reactive.ReactorHttpHandlerAdapter Reactor},
|
||||
* {@linkplain org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter RxNetty}, or
|
||||
* {@linkplain org.springframework.http.server.reactive.UndertowHttpHandlerAdapter Undertow}.
|
||||
* <ul>
|
||||
* <li>Servlet 3.1+ using the
|
||||
* {@link org.springframework.http.server.reactive.ServletHttpHandlerAdapter},</li>
|
||||
* <li>Reactor using the
|
||||
* {@link org.springframework.http.server.reactive.ReactorHttpHandlerAdapter},</li>
|
||||
* <li>RxNetty using the
|
||||
* {@link org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter}, or </li>
|
||||
* <li>Undertow using the
|
||||
* {@link org.springframework.http.server.reactive.UndertowHttpHandlerAdapter}.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param routingFunction the routing function to convert
|
||||
* @param configuration the configuration to use
|
||||
@@ -156,10 +159,10 @@ public abstract class RoutingFunctions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given {@linkplain RoutingFunction routing function} into a {@link HandlerMapping}.
|
||||
* Converts the given {@code RoutingFunction} into a {@code HandlerMapping}.
|
||||
* This conversion uses the {@linkplain Configuration#builder() default configuration}.
|
||||
*
|
||||
* <p>The returned {@code HttpHandler} can be run in a
|
||||
* <p>The returned {@code HandlerMapping} can be run in a
|
||||
* {@link org.springframework.web.reactive.DispatcherHandler}.
|
||||
*
|
||||
* @param routingFunction the routing function to convert
|
||||
@@ -175,7 +178,7 @@ public abstract class RoutingFunctions {
|
||||
* Converts the given {@linkplain RoutingFunction routing function} into a {@link HandlerMapping}
|
||||
* using the given configuration.
|
||||
*
|
||||
* <p>The returned {@code HttpHandler} can be run in a
|
||||
* <p>The returned {@code HandlerMapping} can be run in a
|
||||
* {@link org.springframework.web.reactive.DispatcherHandler}.
|
||||
*
|
||||
* @param routingFunction the routing function to convert
|
||||
@@ -210,4 +213,8 @@ public abstract class RoutingFunctions {
|
||||
return (HandlerFunction<T>) NOT_FOUND_HANDLER;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T> HandlerFunction<T> cast(HandlerFunction<?> handlerFunction) {
|
||||
return (HandlerFunction<T>) handlerFunction;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,16 @@ public class ResponseResultHandler implements HandlerResultHandler {
|
||||
|
||||
private final Configuration configuration;
|
||||
|
||||
/**
|
||||
* Create a {@code ResponseResultHandler} with a default configuration.
|
||||
*/
|
||||
public ResponseResultHandler() {
|
||||
this(Configuration.builder().build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code ResponseResultHandler} with the given configuration.
|
||||
*/
|
||||
public ResponseResultHandler(Configuration configuration) {
|
||||
Assert.notNull(configuration, "'configuration' must not be null");
|
||||
this.configuration = configuration;
|
||||
@@ -46,8 +52,9 @@ public class ResponseResultHandler implements HandlerResultHandler {
|
||||
|
||||
@Override
|
||||
public boolean supports(HandlerResult result) {
|
||||
Object returnValue = result.getReturnValue().orElse(null);
|
||||
return returnValue instanceof Response;
|
||||
return result.getReturnValue()
|
||||
.filter(o -> o instanceof Response)
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -213,7 +213,6 @@ public class DefaultResponseBuilderTests {
|
||||
assertNull(response.getBody());
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Test
|
||||
public void bodyPopulator() throws Exception {
|
||||
String body = "foo";
|
||||
@@ -246,81 +245,6 @@ public class DefaultResponseBuilderTests {
|
||||
assertNotNull(response.getBody());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@Test
|
||||
public void bodyNotAcceptable() throws Exception {
|
||||
String body = "foo";
|
||||
Response<String> result = Response.ok().contentType(MediaType.APPLICATION_JSON).body(body);
|
||||
assertEquals(body, result.body());
|
||||
|
||||
MockServerHttpRequest request =
|
||||
new MockServerHttpRequest(HttpMethod.GET, "http://localhost");
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
ServerWebExchange exchange =
|
||||
new DefaultServerWebExchange(request, response, new MockWebSessionManager());
|
||||
|
||||
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
|
||||
messageWriters.add(new EncoderHttpMessageWriter<CharSequence>(new CharSequenceEncoder()));
|
||||
|
||||
Configuration configuration = mock(Configuration.class);
|
||||
when(configuration.messageWriters()).thenReturn(messageWriters::stream);
|
||||
|
||||
result.writeTo(exchange, configuration).block();
|
||||
assertEquals(HttpStatus.NOT_ACCEPTABLE, response.getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stream() throws Exception {
|
||||
Publisher<String> publisher = Flux.just("foo", "bar");
|
||||
Response<Publisher<String>> result = Response.ok().stream(publisher, String.class);
|
||||
|
||||
MockServerHttpRequest request =
|
||||
new MockServerHttpRequest(HttpMethod.GET, "http://localhost");
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
ServerWebExchange exchange =
|
||||
new DefaultServerWebExchange(request, response, new MockWebSessionManager());
|
||||
|
||||
List<HttpMessageWriter<?>> messageWriters = new ArrayList<>();
|
||||
messageWriters.add(new EncoderHttpMessageWriter<CharSequence>(new CharSequenceEncoder()));
|
||||
|
||||
Configuration mockConfig = mock(Configuration.class);
|
||||
when(mockConfig.messageWriters()).thenReturn(messageWriters::stream);
|
||||
exchange.getAttributes().put(RoutingFunctions.CONFIGURATION_ATTRIBUTE, mockConfig);
|
||||
|
||||
result.writeTo(exchange).block();
|
||||
assertNotNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resource() throws Exception {
|
||||
Resource resource = new ClassPathResource("response.txt", DefaultResponseBuilderTests.class);
|
||||
Response<Resource> result = Response.ok().resource(resource);
|
||||
|
||||
ServerWebExchange exchange = mock(ServerWebExchange.class);
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
when(exchange.getResponse()).thenReturn(response);
|
||||
|
||||
|
||||
result.writeTo(exchange).block();
|
||||
assertNotNull(response.getBody());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sse() throws Exception {
|
||||
ServerSentEvent<String> sse = ServerSentEvent.<String>builder().data("42").build();
|
||||
Mono<ServerSentEvent<String>> body = Mono.just(sse);
|
||||
Response<Mono<ServerSentEvent<String>>> result = Response.ok().sse(body);
|
||||
|
||||
ServerWebExchange exchange = mock(ServerWebExchange.class);
|
||||
MockServerHttpResponse response = new MockServerHttpResponse();
|
||||
when(exchange.getResponse()).thenReturn(response);
|
||||
|
||||
result.writeTo(exchange).block();
|
||||
assertNotNull(response.getBodyWithFlush());
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void render() throws Exception {
|
||||
Map<String, Object> model = Collections.singletonMap("foo", "bar");
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.web.reactive.function.BodyExtractors.toMono;
|
||||
import static org.springframework.web.reactive.function.BodyPopulators.fromPublisher;
|
||||
import static org.springframework.web.reactive.function.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.RequestPredicates.POST;
|
||||
import static org.springframework.web.reactive.function.RoutingFunctions.route;
|
||||
@@ -98,19 +99,19 @@ public class PublisherHandlerFunctionIntegrationTests
|
||||
|
||||
public Response<Publisher<Person>> mono(Request request) {
|
||||
Person person = new Person("John");
|
||||
return Response.ok().body(BodyPopulators.fromPublisher(Mono.just(person), Person.class));
|
||||
return Response.ok().body(fromPublisher(Mono.just(person), Person.class));
|
||||
}
|
||||
|
||||
public Response<Publisher<Person>> postMono(Request request) {
|
||||
Mono<Person> personMono = request.body(toMono(Person.class));
|
||||
return Response.ok().body(BodyPopulators.fromPublisher(personMono, Person.class));
|
||||
return Response.ok().body(fromPublisher(personMono, Person.class));
|
||||
}
|
||||
|
||||
public Response<Publisher<Person>> flux(Request request) {
|
||||
Person person1 = new Person("John");
|
||||
Person person2 = new Person("Jane");
|
||||
return Response.ok().body(
|
||||
BodyPopulators.fromPublisher(Flux.just(person1, person2), Person.class));
|
||||
fromPublisher(Flux.just(person1, person2), Person.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user