Add remote server support classes

Add MVC style Dispatcher, Mapper and Handler classes to support remote
server calls. Spring MVC is not used directly since it may not be on the
classpath (for example if the user is developing a Jersey application).

See gh-3086
pull/3077/merge
Phillip Webb 10 years ago
parent bd945c7b39
commit 505cad48c1

@ -0,0 +1,49 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import org.springframework.http.server.ServerHttpRequest;
/**
* Provides access control for a {@link Dispatcher}.
*
* @author Phillip Webb
* @since 1.3.0
*/
public interface AccessManager {
/**
* {@link AccessManager} that permits all requests.
*/
public static final AccessManager PERMIT_ALL = new AccessManager() {
@Override
public boolean isAllowed(ServerHttpRequest request) {
return true;
}
};
/**
* Determine if the specific request is allowed to be handled by the
* {@link Dispatcher}.
* @param request the request to check
* @return {@code true} if access is allowed.
*/
boolean isAllowed(ServerHttpRequest request);
}

@ -0,0 +1,81 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.Assert;
/**
* Dispatcher used to route incoming remote server requests to a {@link Handler}. Similar
* to {@code DispatchServlet} in Spring MVC but separate to ensure that remote support can
* be used regardless of any web framework.
*
* @author Phillip Webb
* @since 1.3.0
* @see HandlerMapper
*/
public class Dispatcher {
private final AccessManager accessManager;
private final List<HandlerMapper> mappers;
public Dispatcher(AccessManager accessManager, Collection<HandlerMapper> mappers) {
Assert.notNull(accessManager, "AccessManager must not be null");
Assert.notNull(mappers, "Mappers must not be null");
this.accessManager = accessManager;
this.mappers = new ArrayList<HandlerMapper>(mappers);
AnnotationAwareOrderComparator.sort(this.mappers);
}
/**
* Dispatch the specified request to an appropriate {@link Handler}.
* @param request the request
* @param response the response
* @return {@code true} if the request was dispatched
* @throws IOException
*/
public boolean handle(ServerHttpRequest request, ServerHttpResponse response)
throws IOException {
for (HandlerMapper mapper : this.mappers) {
Handler handler = mapper.getHandler(request);
if (handler != null) {
handle(handler, request, response);
return true;
}
}
return false;
}
private void handle(Handler handler, ServerHttpRequest request,
ServerHttpResponse response) throws IOException {
if (!this.accessManager.isAllowed(request)) {
response.setStatusCode(HttpStatus.FORBIDDEN);
return;
}
handler.handle(request, response);
}
}

@ -0,0 +1,81 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.util.Assert;
/**
* Servlet filter providing integration with the remote server {@link Dispatcher}.
*
* @author Phillip Webb
* @author Rob Winch
* @since 1.3.0
*/
public class DispatcherFilter implements Filter {
private final Dispatcher dispatcher;
public DispatcherFilter(Dispatcher dispatcher) {
Assert.notNull(dispatcher, "Dispatcher must not be null");
this.dispatcher = dispatcher;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest
&& response instanceof HttpServletResponse) {
doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
}
else {
chain.doFilter(request, response);
}
}
private void doFilter(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
ServerHttpRequest serverRequest = new ServletServerHttpRequest(request);
ServerHttpResponse serverResponse = new ServletServerHttpResponse(response);
if (!this.dispatcher.handle(serverRequest, serverResponse)) {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}

@ -0,0 +1,41 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import java.io.IOException;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
/**
* A single handler that is able to process an incoming remote server request.
*
* @author Phillip Webb
* @since 1.3.0
*/
public interface Handler {
/**
* Handle the request.
* @param request the request
* @param response the response
* @throws IOException
*/
void handle(ServerHttpRequest request, ServerHttpResponse response)
throws IOException;
}

@ -0,0 +1,37 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import org.springframework.http.server.ServerHttpRequest;
/**
* Interface to provide a mapping between a {@link ServerHttpRequest} and a
* {@link Handler}.
*
* @author Phillip Webb
* @since 1.3.0
*/
public interface HandlerMapper {
/**
* Return the handler for the given request or {@code null}.
* @param request the request
* @return a {@link Handler} or {@code null}
*/
Handler getHandler(ServerHttpRequest request);
}

@ -0,0 +1,59 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import java.io.IOException;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.util.Assert;
/**
* {@link Handler} that responds with a specific {@link HttpStatus}.
*
* @author Phillip Webb
*/
public class HttpStatusHandler implements Handler {
private final HttpStatus status;
/**
* Create a new {@link HttpStatusHandler} instance that will respond with a HTTP OK 200
* status.
*/
public HttpStatusHandler() {
this(HttpStatus.OK);
}
/**
* Create a new {@link HttpStatusHandler} instance that will respond with the specified
* status.
* @param status the status
*/
public HttpStatusHandler(HttpStatus status) {
Assert.notNull(status, "Status must not be null");
this.status = status;
}
@Override
public void handle(ServerHttpRequest request, ServerHttpResponse response)
throws IOException {
response.setStatusCode(this.status);
}
}

@ -0,0 +1,55 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.util.Assert;
/**
* {@link HandlerMapper} implementation that maps incoming URLs
*
* @author Rob Winch
* @author Phillip Webb
* @since 1.3.0
*/
public class UrlHandlerMapper implements HandlerMapper {
private final String requestUri;
private final Handler hander;
/**
* Create a new {@link UrlHandlerMapper}.
* @param url the URL to map
* @param handler the handler to use
*/
public UrlHandlerMapper(String url, Handler handler) {
Assert.hasLength(url, "URL must not be empty");
Assert.isTrue(url.startsWith("/"), "URL must start with '/'");
this.requestUri = url;
this.hander = handler;
}
@Override
public Handler getHandler(ServerHttpRequest request) {
if (this.requestUri.equals(request.getURI().getPath())) {
return this.hander;
}
return null;
}
}

@ -0,0 +1,21 @@
/*
* Copyright 2012-2015 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.
*/
/**
* Server support for a remotely running Spring Boot application.
*/
package org.springframework.boot.developertools.remote.server;

@ -0,0 +1,120 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.willReturn;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
/**
* Tests for {@link DispatcherFilter}.
*
* @author Phillip Webb
*/
public class DispatcherFilterTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Mock
private Dispatcher dispatcher;
@Mock
private FilterChain chain;
@Captor
private ArgumentCaptor<ServerHttpResponse> serverResponseCaptor;
@Captor
private ArgumentCaptor<ServerHttpRequest> serverRequestCaptor;
private DispatcherFilter filter;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
this.filter = new DispatcherFilter(this.dispatcher);
}
@Test
public void dispatcherMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Dispatcher must not be null");
new DispatcherFilter(null);
}
@Test
public void ignoresNotServletRequests() throws Exception {
ServletRequest request = mock(ServletRequest.class);
ServletResponse response = mock(ServletResponse.class);
this.filter.doFilter(request, response, this.chain);
verifyZeroInteractions(this.dispatcher);
verify(this.chain).doFilter(request, response);
}
@Test
public void ignoredByDispatcher() throws Exception {
HttpServletRequest request = new MockHttpServletRequest("GET", "/hello");
HttpServletResponse response = new MockHttpServletResponse();
this.filter.doFilter(request, response, this.chain);
verify(this.chain).doFilter(request, response);
}
@Test
public void handledByDispatcher() throws Exception {
HttpServletRequest request = new MockHttpServletRequest("GET", "/hello");
HttpServletResponse response = new MockHttpServletResponse();
willReturn(true).given(this.dispatcher).handle(any(ServerHttpRequest.class),
any(ServerHttpResponse.class));
this.filter.doFilter(request, response, this.chain);
verifyZeroInteractions(this.chain);
verify(this.dispatcher).handle(this.serverRequestCaptor.capture(),
this.serverResponseCaptor.capture());
ServerHttpRequest dispatcherRequest = this.serverRequestCaptor.getValue();
ServletServerHttpRequest actualRequest = (ServletServerHttpRequest) dispatcherRequest;
ServerHttpResponse dispatcherResponse = this.serverResponseCaptor.getValue();
ServletServerHttpResponse actualResponse = (ServletServerHttpResponse) dispatcherResponse;
assertThat(actualRequest.getServletRequest(), equalTo(request));
assertThat(actualResponse.getServletResponse(), equalTo(response));
}
}

@ -0,0 +1,135 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.core.Ordered;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.withSettings;
/**
* Tests for {@link Dispatcher}.
*
* @author Phillip Webb
*/
public class DispatcherTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
@Mock
private AccessManager accessManager;
private MockHttpServletRequest request;
private MockHttpServletResponse response;
private ServerHttpRequest serverRequest;
private ServerHttpResponse serverResponse;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
this.request = new MockHttpServletRequest();
this.response = new MockHttpServletResponse();
this.serverRequest = new ServletServerHttpRequest(this.request);
this.serverResponse = new ServletServerHttpResponse(this.response);
}
@Test
public void accessManagerMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("AccessManager must not be null");
new Dispatcher(null, Collections.<HandlerMapper> emptyList());
}
@Test
public void mappersMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Mappers must not be null");
new Dispatcher(this.accessManager, null);
}
@Test
public void accessManagerVetoRequest() throws Exception {
given(this.accessManager.isAllowed(any(ServerHttpRequest.class))).willReturn(
false);
HandlerMapper mapper = mock(HandlerMapper.class);
Handler handler = mock(Handler.class);
given(mapper.getHandler(any(ServerHttpRequest.class))).willReturn(handler);
Dispatcher dispatcher = new Dispatcher(this.accessManager,
Collections.singleton(mapper));
dispatcher.handle(this.serverRequest, this.serverResponse);
verifyZeroInteractions(handler);
assertThat(this.response.getStatus(), equalTo(403));
}
@Test
public void accessManagerAllowRequest() throws Exception {
given(this.accessManager.isAllowed(any(ServerHttpRequest.class)))
.willReturn(true);
HandlerMapper mapper = mock(HandlerMapper.class);
Handler handler = mock(Handler.class);
given(mapper.getHandler(any(ServerHttpRequest.class))).willReturn(handler);
Dispatcher dispatcher = new Dispatcher(this.accessManager,
Collections.singleton(mapper));
dispatcher.handle(this.serverRequest, this.serverResponse);
verify(handler).handle(this.serverRequest, this.serverResponse);
}
@Test
public void ordersMappers() throws Exception {
HandlerMapper mapper1 = mock(HandlerMapper.class,
withSettings().extraInterfaces(Ordered.class));
HandlerMapper mapper2 = mock(HandlerMapper.class,
withSettings().extraInterfaces(Ordered.class));
given(((Ordered) mapper1).getOrder()).willReturn(1);
given(((Ordered) mapper2).getOrder()).willReturn(2);
List<HandlerMapper> mappers = Arrays.asList(mapper2, mapper1);
Dispatcher dispatcher = new Dispatcher(AccessManager.PERMIT_ALL, mappers);
dispatcher.handle(this.serverRequest, this.serverResponse);
InOrder inOrder = inOrder(mapper1, mapper2);
inOrder.verify(mapper1).getHandler(this.serverRequest);
inOrder.verify(mapper2).getHandler(this.serverRequest);
}
}

@ -0,0 +1,81 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/**
* Tests for {@link HttpStatusHandler}.
*
* @author Phillip Webb
*/
public class HttpStatusHandlerTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private MockHttpServletRequest servletRequest;
private MockHttpServletResponse servletResponse;
private ServerHttpResponse response;
private ServerHttpRequest request;
@Before
public void setup() {
this.servletRequest = new MockHttpServletRequest();
this.servletResponse = new MockHttpServletResponse();
this.request = new ServletServerHttpRequest(this.servletRequest);
this.response = new ServletServerHttpResponse(this.servletResponse);
}
@Test
public void statusMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("Status must not be null");
new HttpStatusHandler(null);
}
@Test
public void respondsOk() throws Exception {
HttpStatusHandler handler = new HttpStatusHandler();
handler.handle(this.request, this.response);
assertThat(this.servletResponse.getStatus(), equalTo(200));
}
@Test
public void respondsWithStatus() throws Exception {
HttpStatusHandler handler = new HttpStatusHandler(HttpStatus.I_AM_A_TEAPOT);
handler.handle(this.request, this.response);
assertThat(this.servletResponse.getStatus(), equalTo(418));
}
}

@ -0,0 +1,84 @@
/*
* Copyright 2012-2015 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.boot.developertools.remote.server;
import javax.servlet.http.HttpServletRequest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.mock.web.MockHttpServletRequest;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.nullValue;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link UrlHandlerMapper}.
*
* @author Rob Winch
* @author Phillip Webb
*/
public class UrlHandlerMapperTests {
@Rule
public ExpectedException thrown = ExpectedException.none();
private Handler handler = mock(Handler.class);
@Test
public void requestUriMustNotBeNull() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("URL must not be empty");
new UrlHandlerMapper(null, this.handler);
}
@Test
public void requestUriMustNotBeEmpty() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("URL must not be empty");
new UrlHandlerMapper("", this.handler);
}
@Test
public void requestUrlMustStartWithSlash() throws Exception {
this.thrown.expect(IllegalArgumentException.class);
this.thrown.expectMessage("URL must start with '/'");
new UrlHandlerMapper("tunnel", this.handler);
}
@Test
public void handlesMatchedUrl() throws Exception {
UrlHandlerMapper mapper = new UrlHandlerMapper("/tunnel", this.handler);
HttpServletRequest servletRequest = new MockHttpServletRequest("GET", "/tunnel");
ServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
assertThat(mapper.getHandler(request), equalTo(this.handler));
}
@Test
public void ignoresDifferentUrl() throws Exception {
UrlHandlerMapper mapper = new UrlHandlerMapper("/tunnel", this.handler);
HttpServletRequest servletRequest = new MockHttpServletRequest("GET",
"/tunnel/other");
ServerHttpRequest request = new ServletServerHttpRequest(servletRequest);
assertThat(mapper.getHandler(request), nullValue());
}
}
Loading…
Cancel
Save