Polish + minor HttpHandler refactoring
CompositeHttpHandler is public and called ContextPathCompositeHandler. Also an overhaul of the Javadoc on HttpHandler, WebHttpHandlerAdapter, and ContextPathCompositeHandler.
This commit is contained in:
		
							parent
							
								
									57d2fcef55
								
							
						
					
					
						commit
						d39da1d06d
					
				| 
						 | 
				
			
			@ -1,73 +0,0 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.http.server.reactive;
 | 
			
		||||
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.util.Assert;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
 | 
			
		||||
import reactor.core.publisher.Mono;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Composite HttpHandler that selects the handler to use by context path.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Rossen Stoyanchev
 | 
			
		||||
 */
 | 
			
		||||
class CompositeHttpHandler implements HttpHandler {
 | 
			
		||||
 | 
			
		||||
	private final Map<String, HttpHandler> handlerMap;
 | 
			
		||||
 | 
			
		||||
	public CompositeHttpHandler(Map<String, ? extends HttpHandler> handlerMap) {
 | 
			
		||||
		Assert.notEmpty(handlerMap, "Handler map must not be empty");
 | 
			
		||||
		this.handlerMap = initHandlerMap(handlerMap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static Map<String, HttpHandler> initHandlerMap(
 | 
			
		||||
			Map<String, ? extends HttpHandler> inputMap) {
 | 
			
		||||
		inputMap.keySet().stream().forEach(CompositeHttpHandler::validateContextPath);
 | 
			
		||||
		return new LinkedHashMap<>(inputMap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void validateContextPath(String contextPath) {
 | 
			
		||||
		Assert.hasText(contextPath, "Context path must not be empty");
 | 
			
		||||
		if (!contextPath.equals("/")) {
 | 
			
		||||
			Assert.isTrue(contextPath.startsWith("/"),
 | 
			
		||||
					"Context path must begin with '/'");
 | 
			
		||||
			Assert.isTrue(!contextPath.endsWith("/"),
 | 
			
		||||
					"Context path must not end with '/'");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
 | 
			
		||||
		String path = getPathToUse(request);
 | 
			
		||||
		return this.handlerMap.entrySet().stream().filter(
 | 
			
		||||
				entry -> path.startsWith(entry.getKey())).findFirst().map(entry -> {
 | 
			
		||||
					// Preserve "native" contextPath from underlying request..
 | 
			
		||||
					String contextPath = request.getContextPath() + entry.getKey();
 | 
			
		||||
					ServerHttpRequest mutatedRequest = request.mutate().contextPath(
 | 
			
		||||
							contextPath).build();
 | 
			
		||||
					HttpHandler handler = entry.getValue();
 | 
			
		||||
					return handler.handle(mutatedRequest, response);
 | 
			
		||||
				}).orElseGet(() -> {
 | 
			
		||||
					response.setStatusCode(HttpStatus.NOT_FOUND);
 | 
			
		||||
					response.setComplete();
 | 
			
		||||
					return Mono.empty();
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Strip the context path from the native request, if any.
 | 
			
		||||
	 */
 | 
			
		||||
	private String getPathToUse(ServerHttpRequest request) {
 | 
			
		||||
		String path = request.getURI().getRawPath();
 | 
			
		||||
		String contextPath = request.getContextPath();
 | 
			
		||||
		if (!StringUtils.hasText(contextPath)) {
 | 
			
		||||
			return path;
 | 
			
		||||
		}
 | 
			
		||||
		int contextLength = contextPath.length();
 | 
			
		||||
		return (path.length() > contextLength ? path.substring(contextLength) : "");
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,82 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.http.server.reactive;
 | 
			
		||||
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.HttpStatus;
 | 
			
		||||
import org.springframework.util.Assert;
 | 
			
		||||
import org.springframework.util.StringUtils;
 | 
			
		||||
 | 
			
		||||
import reactor.core.publisher.Mono;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@code HttpHandler} delegating requests to one of several {@code HttpHandler}'s
 | 
			
		||||
 * based on simple, prefix-based mappings.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>This is intended as a coarse-grained mechanism for delegating requests to
 | 
			
		||||
 * one of several applications -- each represented by an {@code HttpHandler}, with
 | 
			
		||||
 * the application "context path" (the prefix-based mapping) exposed via
 | 
			
		||||
 * {@link ServerHttpRequest#getContextPath()}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Rossen Stoyanchev
 | 
			
		||||
 * @since 5.0
 | 
			
		||||
 */
 | 
			
		||||
public class ContextPathCompositeHandler implements HttpHandler {
 | 
			
		||||
 | 
			
		||||
	private final Map<String, HttpHandler> handlerMap;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	public ContextPathCompositeHandler(Map<String, ? extends HttpHandler> handlerMap) {
 | 
			
		||||
		Assert.notEmpty(handlerMap, "Handler map must not be empty");
 | 
			
		||||
		this.handlerMap = initHandlers(handlerMap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static Map<String, HttpHandler> initHandlers(Map<String, ? extends HttpHandler> map) {
 | 
			
		||||
		map.keySet().forEach(ContextPathCompositeHandler::assertValidContextPath);
 | 
			
		||||
		return new LinkedHashMap<>(map);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private static void assertValidContextPath(String contextPath) {
 | 
			
		||||
		Assert.hasText(contextPath, "Context path must not be empty");
 | 
			
		||||
		if (contextPath.equals("/")) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		Assert.isTrue(contextPath.startsWith("/"), "Context path must begin with '/'");
 | 
			
		||||
		Assert.isTrue(!contextPath.endsWith("/"), "Context path must not end with '/'");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
 | 
			
		||||
		String path = getPathWithinApplication(request);
 | 
			
		||||
		return this.handlerMap.entrySet().stream()
 | 
			
		||||
				.filter(entry -> path.startsWith(entry.getKey()))
 | 
			
		||||
				.findFirst()
 | 
			
		||||
				.map(entry -> {
 | 
			
		||||
					String contextPath = request.getContextPath() + entry.getKey();
 | 
			
		||||
					ServerHttpRequest newRequest = request.mutate().contextPath(contextPath).build();
 | 
			
		||||
					return entry.getValue().handle(newRequest, response);
 | 
			
		||||
				})
 | 
			
		||||
				.orElseGet(() -> {
 | 
			
		||||
					response.setStatusCode(HttpStatus.NOT_FOUND);
 | 
			
		||||
					response.setComplete();
 | 
			
		||||
					return Mono.empty();
 | 
			
		||||
				});
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Get the path within the "native" context path of the underlying server,
 | 
			
		||||
	 * for example when running on a Servlet container.
 | 
			
		||||
	 */
 | 
			
		||||
	private String getPathWithinApplication(ServerHttpRequest request) {
 | 
			
		||||
		String path = request.getURI().getRawPath();
 | 
			
		||||
		String contextPath = request.getContextPath();
 | 
			
		||||
		if (!StringUtils.hasText(contextPath)) {
 | 
			
		||||
			return path;
 | 
			
		||||
		}
 | 
			
		||||
		int length = contextPath.length();
 | 
			
		||||
		return (path.length() > length ? path.substring(length) : "");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -16,35 +16,38 @@
 | 
			
		|||
 | 
			
		||||
package org.springframework.http.server.reactive;
 | 
			
		||||
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import reactor.core.publisher.Mono;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Contract for handling HTTP requests in a non-blocking way.
 | 
			
		||||
 * Lowest level contract for reactive HTTP request handling that serves as a
 | 
			
		||||
 * common denominator across different runtimes.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Higher-level, but still generic, building blocks for applications such as
 | 
			
		||||
 * {@code WebFilter}, {@code WebSession}, {@code ServerWebExchange}, and others
 | 
			
		||||
 * are available in the {@link org.springframework.web.server} package.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Application level programming models such as annotated controllers and
 | 
			
		||||
 * functional handlers are available in the {@code spring-webflux} module.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Typically an {@link HttpHandler} represents an entire application with
 | 
			
		||||
 * higher-level programming models bridged via
 | 
			
		||||
 * {@link org.springframework.web.server.adapter.WebHttpHandlerBuilder
 | 
			
		||||
 * WebHttpHandlerBuilder}. Multiple applications at unique context paths can be
 | 
			
		||||
 * plugged in with the help of the {@link ContextPathCompositeHandler}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Arjen Poutsma
 | 
			
		||||
 * @author Rossen Stoyanchev
 | 
			
		||||
 * @since 5.0
 | 
			
		||||
 * @see ContextPathCompositeHandler
 | 
			
		||||
 */
 | 
			
		||||
public interface HttpHandler {
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Handle the given request and generate a response.
 | 
			
		||||
	 * @param request current HTTP request
 | 
			
		||||
	 * @param response current HTTP response
 | 
			
		||||
	 * @return {@code Mono<Void>} to indicate when request handling is complete
 | 
			
		||||
	 * Handle the given request and write to the response.
 | 
			
		||||
	 * @param request current request
 | 
			
		||||
	 * @param response current response
 | 
			
		||||
	 * @return indicates completion of request handling
 | 
			
		||||
	 */
 | 
			
		||||
	Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Return a composite {@link HttpHandler} that maps multiple
 | 
			
		||||
	 * {@link HttpHandler}s each mapped to a distinct context path.
 | 
			
		||||
	 * @param handlerMap the source handler map
 | 
			
		||||
	 * @return a composite {@link HttpHandler}
 | 
			
		||||
	 */
 | 
			
		||||
	static HttpHandler of(Map<String, ? extends HttpHandler> handlerMap) {
 | 
			
		||||
		return new CompositeHttpHandler(handlerMap);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,6 +48,7 @@ public class ReactorHttpHandlerAdapter
 | 
			
		|||
		this.httpHandler = httpHandler;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
	public Mono<Void> apply(HttpServerRequest request, HttpServerResponse response) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ import rx.RxReactiveStreams;
 | 
			
		|||
 */
 | 
			
		||||
public class RxNettyHttpHandlerAdapter implements RequestHandler<ByteBuf, ByteBuf> {
 | 
			
		||||
 | 
			
		||||
	private static final Log logger = LogFactory.getLog(ReactorHttpHandlerAdapter.class);
 | 
			
		||||
	private static final Log logger = LogFactory.getLog(RxNettyHttpHandlerAdapter.class);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	private final HttpHandler httpHandler;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,7 +48,7 @@ import org.springframework.util.Assert;
 | 
			
		|||
@SuppressWarnings("serial")
 | 
			
		||||
public class ServletHttpHandlerAdapter implements Servlet {
 | 
			
		||||
 | 
			
		||||
	private static final Log logger = LogFactory.getLog(ReactorHttpHandlerAdapter.class);
 | 
			
		||||
	private static final Log logger = LogFactory.getLog(ServletHttpHandlerAdapter.class);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	private static final int DEFAULT_BUFFER_SIZE = 8192;
 | 
			
		||||
| 
						 | 
				
			
			@ -110,12 +110,18 @@ public class ServletHttpHandlerAdapter implements Servlet {
 | 
			
		|||
		this.httpHandler.handle(httpRequest, httpResponse).subscribe(subscriber);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected ServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context) throws IOException {
 | 
			
		||||
		return new ServletServerHttpRequest(request, context, getDataBufferFactory(), getBufferSize());
 | 
			
		||||
	protected ServerHttpRequest createRequest(HttpServletRequest request,
 | 
			
		||||
			AsyncContext context) throws IOException {
 | 
			
		||||
 | 
			
		||||
		return new ServletServerHttpRequest(
 | 
			
		||||
				request, context, getDataBufferFactory(), getBufferSize());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected ServerHttpResponse createResponse(HttpServletResponse response, AsyncContext context) throws IOException {
 | 
			
		||||
		return new ServletServerHttpResponse(response, context, getDataBufferFactory(), getBufferSize());
 | 
			
		||||
	protected ServerHttpResponse createResponse(HttpServletResponse response,
 | 
			
		||||
			AsyncContext context) throws IOException {
 | 
			
		||||
 | 
			
		||||
		return new ServletServerHttpResponse(
 | 
			
		||||
				response, context, getDataBufferFactory(), getBufferSize());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ import org.springframework.util.Assert;
 | 
			
		|||
 */
 | 
			
		||||
public class UndertowHttpHandlerAdapter implements io.undertow.server.HttpHandler {
 | 
			
		||||
 | 
			
		||||
	private static final Log logger = LogFactory.getLog(ReactorHttpHandlerAdapter.class);
 | 
			
		||||
	private static final Log logger = LogFactory.getLog(UndertowHttpHandlerAdapter.class);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	private final HttpHandler httpHandler;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,24 +35,24 @@ import org.springframework.web.server.session.DefaultWebSessionManager;
 | 
			
		|||
import org.springframework.web.server.session.WebSessionManager;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Builder for an {@link HttpHandler} that adapts to a target {@link WebHandler}
 | 
			
		||||
 * along with a chain of {@link WebFilter}s and a set of
 | 
			
		||||
 * {@link WebExceptionHandler}s.
 | 
			
		||||
 * This builder has two purposes.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>Example usage:
 | 
			
		||||
 * <pre>
 | 
			
		||||
 * WebFilter filter = ... ;
 | 
			
		||||
 * WebHandler webHandler = ... ;
 | 
			
		||||
 * WebExceptionHandler exceptionHandler = ...;
 | 
			
		||||
 * <p>One is to assemble a processing chain that consists of a target
 | 
			
		||||
 * {@link WebHandler}, then decorated with a set of {@link WebFilter}'s, then
 | 
			
		||||
 * further decorated with a set of {@link WebExceptionHandler}'s.
 | 
			
		||||
 *
 | 
			
		||||
 * HttpHandler httpHandler = WebHttpHandlerBuilder.webHandler(webHandler)
 | 
			
		||||
 *         .filters(filter)
 | 
			
		||||
 *         .exceptionHandlers(exceptionHandler)
 | 
			
		||||
 *         .build();
 | 
			
		||||
 * </pre>
 | 
			
		||||
 * <p>The second purpose is to adapt the resulting processing chain to an
 | 
			
		||||
 * {@link HttpHandler} -- the lowest level reactive HTTP handling abstraction,
 | 
			
		||||
 * which can then be used with any of the supported runtimes. The adaptation
 | 
			
		||||
 * is done with the help of {@link HttpWebHandlerAdapter}.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>The processing chain can be assembled manually via builder methods, or
 | 
			
		||||
 * detected from Spring configuration via
 | 
			
		||||
 * {@link #applicationContext(ApplicationContext)}, or a mix of both.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Rossen Stoyanchev
 | 
			
		||||
 * @since 5.0
 | 
			
		||||
 * @see HttpWebHandlerAdapter
 | 
			
		||||
 */
 | 
			
		||||
public class WebHttpHandlerBuilder {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,26 +34,27 @@ import static org.junit.Assert.assertTrue;
 | 
			
		|||
import static org.junit.Assert.fail;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Unit tests for {@link HttpHandler}.
 | 
			
		||||
 * Unit tests for {@link ContextPathCompositeHandler}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author Rossen Stoyanchev
 | 
			
		||||
 */
 | 
			
		||||
public class HttpHandlerTests {
 | 
			
		||||
public class ContextPathCompositeHandlerTests {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@Test
 | 
			
		||||
	public void invalidContextPath() {
 | 
			
		||||
		testInvalidContextPath("  ", "Context path must not be empty");
 | 
			
		||||
		testInvalidContextPath("path", "Context path must begin with '/'");
 | 
			
		||||
		testInvalidContextPath("/path/", "Context path must not end with '/'");
 | 
			
		||||
		testInvalid("  ", "Context path must not be empty");
 | 
			
		||||
		testInvalid("path", "Context path must begin with '/'");
 | 
			
		||||
		testInvalid("/path/", "Context path must not end with '/'");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void testInvalidContextPath(String contextPath, String errorMessage) {
 | 
			
		||||
	private void testInvalid(String contextPath, String expectedError) {
 | 
			
		||||
		try {
 | 
			
		||||
			new TestHttpHandlerAdapter(Collections.singletonMap(contextPath, new TestHttpHandler()));
 | 
			
		||||
			new ContextPathCompositeHandler(Collections.singletonMap(contextPath, new TestHttpHandler()));
 | 
			
		||||
			fail();
 | 
			
		||||
		}
 | 
			
		||||
		catch (IllegalArgumentException ex) {
 | 
			
		||||
			assertEquals(errorMessage, ex.getMessage());
 | 
			
		||||
			assertEquals(expectedError, ex.getMessage());
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,7 @@ public class HttpHandlerTests {
 | 
			
		|||
		map.put("/another/path", handler2);
 | 
			
		||||
		map.put("/yet/another/path", handler3);
 | 
			
		||||
 | 
			
		||||
		testPath("/another/path/and/more", map);
 | 
			
		||||
		testHandle("/another/path/and/more", map);
 | 
			
		||||
 | 
			
		||||
		assertInvoked(handler2, "/another/path");
 | 
			
		||||
		assertNotInvoked(handler1, handler3);
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +86,7 @@ public class HttpHandlerTests {
 | 
			
		|||
		map.put("/another/path", handler2);
 | 
			
		||||
		map.put("/yet/another/path", handler3);
 | 
			
		||||
 | 
			
		||||
		testPath("/path", map);
 | 
			
		||||
		testHandle("/path", map);
 | 
			
		||||
 | 
			
		||||
		assertInvoked(handler1, "/path");
 | 
			
		||||
		assertNotInvoked(handler2, handler3);
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +102,7 @@ public class HttpHandlerTests {
 | 
			
		|||
		TestHttpHandler handler = new TestHttpHandler();
 | 
			
		||||
		Map<String, HttpHandler> map = Collections.singletonMap("/another/path", handler);
 | 
			
		||||
 | 
			
		||||
		new TestHttpHandlerAdapter(map).handle(request);
 | 
			
		||||
		new ContextPathCompositeHandler(map).handle(request, new MockServerHttpResponse());
 | 
			
		||||
 | 
			
		||||
		assertTrue(handler.wasInvoked());
 | 
			
		||||
		assertEquals("/yet/another/path", handler.getRequest().getContextPath());
 | 
			
		||||
| 
						 | 
				
			
			@ -116,16 +117,18 @@ public class HttpHandlerTests {
 | 
			
		|||
		map.put("/path", handler1);
 | 
			
		||||
		map.put("/another/path", handler2);
 | 
			
		||||
 | 
			
		||||
		ServerHttpResponse response = testPath("/yet/another/path", map);
 | 
			
		||||
		ServerHttpResponse response = testHandle("/yet/another/path", map);
 | 
			
		||||
 | 
			
		||||
		assertNotInvoked(handler1, handler2);
 | 
			
		||||
		assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	private ServerHttpResponse testPath(String path, Map<String, HttpHandler> handlerMap) {
 | 
			
		||||
		TestHttpHandlerAdapter adapter = new TestHttpHandlerAdapter(handlerMap);
 | 
			
		||||
		return adapter.handle(path);
 | 
			
		||||
	private ServerHttpResponse testHandle(String pathToHandle, Map<String, HttpHandler> handlerMap) {
 | 
			
		||||
		ServerHttpRequest request = MockServerHttpRequest.get(pathToHandle).build();
 | 
			
		||||
		ServerHttpResponse response = new MockServerHttpResponse();
 | 
			
		||||
		new ContextPathCompositeHandler(handlerMap).handle(request, response);
 | 
			
		||||
		return response;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	private void assertInvoked(TestHttpHandler handler, String contextPath) {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,30 +141,6 @@ public class HttpHandlerTests {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings("WeakerAccess")
 | 
			
		||||
	private static class TestHttpHandlerAdapter {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		private final HttpHandler httpHandler;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public TestHttpHandlerAdapter(Map<String, HttpHandler> handlerMap) {
 | 
			
		||||
			this.httpHandler = HttpHandler.of(handlerMap);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ServerHttpResponse handle(String path) {
 | 
			
		||||
			ServerHttpRequest request = MockServerHttpRequest.get(path).build();
 | 
			
		||||
			return handle(request);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public ServerHttpResponse handle(ServerHttpRequest request) {
 | 
			
		||||
			ServerHttpResponse response = new MockServerHttpResponse();
 | 
			
		||||
			this.httpHandler.handle(request, response);
 | 
			
		||||
			return response;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	@SuppressWarnings("WeakerAccess")
 | 
			
		||||
	private static class TestHttpHandler implements HttpHandler {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,6 +19,7 @@ package org.springframework.http.server.reactive.bootstrap;
 | 
			
		|||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.reactive.ContextPathCompositeHandler;
 | 
			
		||||
import org.springframework.http.server.reactive.HttpHandler;
 | 
			
		||||
import org.springframework.util.Assert;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +80,11 @@ public abstract class AbstractHttpServer implements HttpServer {
 | 
			
		|||
		return this.handlerMap;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	protected HttpHandler resolveHttpHandler() {
 | 
			
		||||
		return getHttpHandlerMap() != null ?
 | 
			
		||||
				new ContextPathCompositeHandler(getHttpHandlerMap()) : getHttpHandler();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// InitializingBean
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ import org.eclipse.jetty.server.Server;
 | 
			
		|||
import org.eclipse.jetty.server.ServerConnector;
 | 
			
		||||
import org.eclipse.jetty.servlet.ServletContextHandler;
 | 
			
		||||
import org.eclipse.jetty.servlet.ServletHolder;
 | 
			
		||||
import org.springframework.http.server.reactive.HttpHandler;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.reactive.JettyHttpHandlerAdapter;
 | 
			
		||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,8 +53,7 @@ public class JettyHttpServer extends AbstractHttpServer {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private ServletHttpHandlerAdapter createServletAdapter() {
 | 
			
		||||
		return new JettyHttpHandlerAdapter(getHttpHandlerMap() != null
 | 
			
		||||
				? HttpHandler.of(getHttpHandlerMap()) : getHttpHandler());
 | 
			
		||||
		return new JettyHttpHandlerAdapter(resolveHttpHandler());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,6 @@ import java.util.concurrent.atomic.AtomicReference;
 | 
			
		|||
import reactor.core.Loopback;
 | 
			
		||||
import reactor.ipc.netty.NettyContext;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.reactive.HttpHandler;
 | 
			
		||||
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -43,8 +42,7 @@ public class ReactorHttpServer extends AbstractHttpServer implements Loopback {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private ReactorHttpHandlerAdapter createHttpHandlerAdapter() {
 | 
			
		||||
		return new ReactorHttpHandlerAdapter(getHttpHandlerMap() != null
 | 
			
		||||
				? HttpHandler.of(getHttpHandlerMap()) : getHttpHandler());
 | 
			
		||||
		return new ReactorHttpHandlerAdapter(resolveHttpHandler());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,6 @@ package org.springframework.http.server.reactive.bootstrap;
 | 
			
		|||
 | 
			
		||||
import io.netty.buffer.ByteBuf;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.reactive.HttpHandler;
 | 
			
		||||
import org.springframework.http.server.reactive.RxNettyHttpHandlerAdapter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -38,8 +37,7 @@ public class RxNettyHttpServer extends AbstractHttpServer {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private RxNettyHttpHandlerAdapter createHttpHandlerAdapter() {
 | 
			
		||||
		return new RxNettyHttpHandlerAdapter(getHttpHandlerMap() != null
 | 
			
		||||
				? HttpHandler.of(getHttpHandlerMap()) : getHttpHandler());
 | 
			
		||||
		return new RxNettyHttpHandlerAdapter(resolveHttpHandler());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ import java.io.File;
 | 
			
		|||
import org.apache.catalina.Context;
 | 
			
		||||
import org.apache.catalina.LifecycleException;
 | 
			
		||||
import org.apache.catalina.startup.Tomcat;
 | 
			
		||||
import org.springframework.http.server.reactive.HttpHandler;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.reactive.ServletHttpHandlerAdapter;
 | 
			
		||||
import org.springframework.http.server.reactive.TomcatHttpHandlerAdapter;
 | 
			
		||||
import org.springframework.util.Assert;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,8 +68,7 @@ public class TomcatHttpServer extends AbstractHttpServer {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private ServletHttpHandlerAdapter initServletAdapter() {
 | 
			
		||||
		return new TomcatHttpHandlerAdapter(getHttpHandlerMap() != null
 | 
			
		||||
				? HttpHandler.of(getHttpHandlerMap()) : getHttpHandler());
 | 
			
		||||
		return new TomcatHttpHandlerAdapter(resolveHttpHandler());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@ import java.net.InetSocketAddress;
 | 
			
		|||
 | 
			
		||||
import io.undertow.Undertow;
 | 
			
		||||
 | 
			
		||||
import org.springframework.http.server.reactive.HttpHandler;
 | 
			
		||||
import org.springframework.http.server.reactive.UndertowHttpHandlerAdapter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -39,8 +38,7 @@ public class UndertowHttpServer extends AbstractHttpServer {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	private UndertowHttpHandlerAdapter initHttpHandlerAdapter() {
 | 
			
		||||
		return new UndertowHttpHandlerAdapter(getHttpHandlerMap() != null
 | 
			
		||||
				? HttpHandler.of(getHttpHandlerMap()) : getHttpHandler());
 | 
			
		||||
		return new UndertowHttpHandlerAdapter(resolveHttpHandler());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	@Override
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,12 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Core interfaces and classes for Spring Web Reactive.
 | 
			
		||||
 * Top-level package for the {@code spring-webflux} module that contains
 | 
			
		||||
 * {@link org.springframework.web.reactive.DispatcherHandler}, the main entry
 | 
			
		||||
 * point for WebFlux server endpoint processing including key contracts used to
 | 
			
		||||
 * map requests to handlers, invoke them, and process the result.
 | 
			
		||||
 *
 | 
			
		||||
 * <p>The module provides two programming models for reactive server endpoints.
 | 
			
		||||
 * One based on annotated {@code @Controller}'s and another based on functional
 | 
			
		||||
 * routing and handling. The module also contains a functional, reactive
 | 
			
		||||
 * {@code WebClient} as well as client and server, reactive WebSocket support.
 | 
			
		||||
 */
 | 
			
		||||
package org.springframework.web.reactive;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue