DATACMNS-335 - PageableHandlerMethodArgumentResolver now has configurable max page size.

The default is set to 2000.
This commit is contained in:
Oliver Gierke
2013-06-10 14:11:26 +02:00
parent 2195e31493
commit 15c4e34716
3 changed files with 53 additions and 11 deletions

View File

@@ -47,8 +47,7 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
* that if you need to stick to the former request parameters an 1-indexed behavior. This will be removed in the next
* major version (1.7). So consider migrating to the new way of exposing request parameters.
*/
@Deprecated
public static final PageableHandlerMethodArgumentResolver LEGACY;
@Deprecated public static final PageableHandlerMethodArgumentResolver LEGACY;
static {
LEGACY = new PageableHandlerMethodArgumentResolver();
@@ -65,6 +64,7 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
private static final String DEFAULT_SIZE_PROPERTY = "size";
private static final String DEFAULT_PREFIX = "";
private static final String DEFAULT_QUALIFIER_SEPARATOR = "_";
private static final int DEFAULT_MAX_PAGE_SIZE = 2000;
private Pageable fallbackPageable = DEFAULT_PAGE_REQUEST;
private SortHandlerMethodArgumentResolver sortResolver = new SortHandlerMethodArgumentResolver();
@@ -72,6 +72,7 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
private String sizeProperty = DEFAULT_SIZE_PROPERTY;
private String prefix = DEFAULT_PREFIX;
private String qualifierSeparator = DEFAULT_QUALIFIER_SEPARATOR;
private int maxPageSize = DEFAULT_MAX_PAGE_SIZE;
private boolean oneIndexedParameters = false;
/**
@@ -88,6 +89,16 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
this.fallbackPageable = fallbackPageable;
}
/**
* Configures the maximum page size to be accepted. This allows to put an upper boundary of the page size to prevent
* potential attacks trying to issue an {@link OutOfMemoryError}. Defaults to {@link #DEFAULT_MAX_PAGE_SIZE}.
*
* @param maxPageSize the maxPageSize to set
*/
public void setMaxPageSize(int maxPageSize) {
this.maxPageSize = maxPageSize;
}
/**
* Configures the parameter name to be used to find the page number in the request. Defaults to {@code page}.
*
@@ -173,12 +184,12 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
Pageable pageable = (Pageable) value;
String pagePropertyName = getParameterNameToUse(pageProperty, parameter);
String propertyToLookup = getParameterNameToUse(sizeProperty, parameter);
String sizePropertyName = getParameterNameToUse(sizeProperty, parameter);
int pageNumber = pageable.getPageNumber();
builder.queryParam(pagePropertyName, oneIndexedParameters ? pageNumber + 1 : pageNumber);
builder.queryParam(propertyToLookup, pageable.getPageSize());
builder.queryParam(sizePropertyName, pageable.getPageSize() <= maxPageSize ? pageable.getPageSize() : maxPageSize);
sortResolver.enhance(builder, parameter, pageable.getSort());
}
@@ -201,6 +212,7 @@ public class PageableHandlerMethodArgumentResolver implements HandlerMethodArgum
: defaultOrFallback.getPageNumber();
int pageSize = StringUtils.hasText(pageSizeString) ? Integer.parseInt(pageSizeString) : defaultOrFallback
.getPageSize();
pageSize = pageSize > maxPageSize ? maxPageSize : pageSize;
Sort sort = sortResolver.resolveArgument(methodParameter, mavContainer, webRequest, binderFactory);
return new PageRequest(page, pageSize, sort == null ? defaultOrFallback.getSort() : sort);

View File

@@ -27,6 +27,7 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.util.UriComponentsBuilder;
@@ -48,8 +49,7 @@ public abstract class PageableDefaultUnitTest {
static final PageRequest REFERENCE_WITH_SORT = new PageRequest(PAGE_NUMBER, PAGE_SIZE, SORT);
static final PageRequest REFERENCE_WITH_SORT_FIELDS = new PageRequest(PAGE_NUMBER, PAGE_SIZE, new Sort(SORT_FIELDS));
@Rule
public ExpectedException exception = ExpectedException.none();
@Rule public ExpectedException exception = ExpectedException.none();
@Test
public void supportsPageable() {
@@ -124,11 +124,16 @@ public abstract class PageableDefaultUnitTest {
resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null);
}
private void assertSupportedAndResult(MethodParameter parameter, Pageable pageable) throws Exception {
protected void assertSupportedAndResult(MethodParameter parameter, Pageable pageable) throws Exception {
assertSupportedAndResult(parameter, pageable, TestUtils.getWebRequest());
}
protected void assertSupportedAndResult(MethodParameter parameter, Pageable pageable, NativeWebRequest request)
throws Exception {
HandlerMethodArgumentResolver resolver = getResolver();
assertThat(resolver.supportsParameter(parameter), is(true));
assertThat(resolver.resolveArgument(parameter, null, TestUtils.getWebRequest(), null), is((Object) pageable));
assertThat(resolver.resolveArgument(parameter, null, request, null), is((Object) pageable));
}
protected void assertUriStringFor(Pageable pageable, String expected) {

View File

@@ -17,9 +17,13 @@ package org.springframework.data.web;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.MethodParameter;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.web.SortDefault.SortDefaults;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.request.ServletWebRequest;
/**
* Unit tests for {@link PageableHandlerMethodArgumentResolver}. Pulls in defaulting tests from
@@ -39,9 +43,30 @@ public class PageableHandlerMethodArgumentResolverUnitTest extends PageableDefau
assertUriStringFor(REFERENCE_WITH_SORT_FIELDS, basicString + "&sort=firstname,lastname,asc");
}
/**
* @see DATACMNS-335
*/
@Test
public void preventsPageSizeFromExceedingMayValueIfConfigured() throws Exception {
// Write side
assertUriStringFor(new PageRequest(0, 200), "page=0&size=100");
// Read side
MockHttpServletRequest request = new MockHttpServletRequest();
request.addParameter("page", "0");
request.addParameter("size", "200");
MethodParameter parameter = new MethodParameter(Sample.class.getMethod("supportedMethod", Pageable.class), 0);
assertSupportedAndResult(parameter, new PageRequest(0, 100), new ServletWebRequest(request));
}
@Override
protected PageableHandlerMethodArgumentResolver getResolver() {
return new PageableHandlerMethodArgumentResolver();
PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
resolver.setMaxPageSize(100);
return resolver;
}
@Override
@@ -57,8 +82,8 @@ public class PageableHandlerMethodArgumentResolverUnitTest extends PageableDefau
void simpleDefault(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER) Pageable pageable);
void simpleDefaultWithSort(
@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER, sort = { "firstname", "lastname" }) Pageable pageable);
void simpleDefaultWithSort(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER,
sort = { "firstname", "lastname" }) Pageable pageable);
void simpleDefaultWithSortAndDirection(@PageableDefault(size = PAGE_SIZE, page = PAGE_NUMBER, sort = { "firstname",
"lastname" }, direction = Direction.DESC) Pageable pageable);