Avoid paging links when offset is artificially set very high

This commit is contained in:
James Agnew 2019-02-25 20:44:22 -05:00
parent fb06664f70
commit 94f9ffa977
2 changed files with 47 additions and 7 deletions

View File

@ -157,6 +157,35 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
} }
@Test
public void testManualPagingLinkOffsetDoesntReturnBeyondEnd() {
myDaoConfig.setSearchPreFetchThresholds(Lists.newArrayList(10, 1000));
for (int i = 0; i < 50; i++) {
Organization o = new Organization();
o.setId("O" + i);
o.setName("O" + i);
ourClient.update().resource(o).execute().getId().toUnqualifiedVersionless();
}
Bundle output = ourClient
.search()
.forResource("Organization")
.count(3)
.returnBundle(Bundle.class)
.execute();
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(output));
String linkNext = output.getLink("next").getUrl();
linkNext = linkNext.replaceAll("_getpagesoffset=[0-9]+", "_getpagesoffset=3300");
assertThat(linkNext, containsString("_getpagesoffset=3300"));
Bundle nextPageBundle = ourClient.loadPage().byUrl(linkNext).andReturnBundle(Bundle.class).execute();
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(nextPageBundle));
assertEquals(null, nextPageBundle.getLink("next"));
}
@Test @Test
public void testSearchLinksWorkWithIncludes() { public void testSearchLinksWorkWithIncludes() {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {

View File

@ -142,6 +142,10 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
} }
RestfulServerUtils.validateResourceListNotNull(resourceList); RestfulServerUtils.validateResourceListNotNull(resourceList);
if (numTotalResults == null) {
numTotalResults = theResult.size();
}
if (theSearchId != null) { if (theSearchId != null) {
searchId = theSearchId; searchId = theSearchId;
} else { } else {
@ -198,7 +202,13 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theResult.getPreviousPageId(), theRequest.getParameters(), prettyPrint, theBundleType); linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theResult.getPreviousPageId(), theRequest.getParameters(), prettyPrint, theBundleType);
} }
} else if (searchId != null) { } else if (searchId != null) {
// We're doing offset pages /*
* We're doing offset pages - Note that we only return paging links if we actually
* included some results in the response. We do this to avoid situations where
* people have faked the offset number to some huge number to avoid them getting
* back paging links that don't make sense.
*/
if (resourceList.size() > 0) {
if (numTotalResults == null || theOffset + numToReturn < numTotalResults) { if (numTotalResults == null || theOffset + numToReturn < numTotalResults) {
linkNext = (RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theOffset + numToReturn, numToReturn, theRequest.getParameters(), prettyPrint, theBundleType)); linkNext = (RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, theOffset + numToReturn, numToReturn, theRequest.getParameters(), prettyPrint, theBundleType));
} }
@ -207,6 +217,7 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, start, theLimit, theRequest.getParameters(), prettyPrint, theBundleType); linkPrev = RestfulServerUtils.createPagingLink(theIncludes, theRequest, searchId, start, theLimit, theRequest.getParameters(), prettyPrint, theBundleType);
} }
} }
}
bundleFactory.addRootPropertiesToBundle(theResult.getUuid(), serverBase, theLinkSelf, linkPrev, linkNext, theResult.size(), theBundleType, theResult.getPublished()); bundleFactory.addRootPropertiesToBundle(theResult.getUuid(), serverBase, theLinkSelf, linkPrev, linkNext, theResult.size(), theBundleType, theResult.getPublished());
bundleFactory.addResourcesToBundle(new ArrayList<>(resourceList), theBundleType, serverBase, theServer.getBundleInclusionRule(), theIncludes); bundleFactory.addResourcesToBundle(new ArrayList<>(resourceList), theBundleType, serverBase, theServer.getBundleInclusionRule(), theIncludes);