diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2958-procedure-patient-consistent-error-handling.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2958-procedure-patient-consistent-error-handling.yaml new file mode 100644 index 00000000000..f90ca63a917 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/5_6_0/2958-procedure-patient-consistent-error-handling.yaml @@ -0,0 +1,6 @@ +--- +type: fix +issue: 2958 +jira: SMILE-643 +title: "Fixed issue where the processing of queries like Procedure?patient= before a cache search would cause the parameter key to be removed. +Additionally, ensured that requests like Procedure?patient cause HTTP 400 Bad Request instead of HTTP 500 Internal Error." diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java index 4d266271bd9..8c1303f1571 100644 --- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java +++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/SearchCoordinatorSvcImpl.java @@ -1014,6 +1014,9 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { logged = true; ourLog.warn("Failed during search due to invalid request: {}", t.toString()); } + }else if (t instanceof java.lang.IllegalArgumentException && t.getMessage().contentEquals("The validated expression is false")) { + logged = true; + ourLog.warn("Failed during search due to invalid request: {}", t.toString()); } if (!logged) { @@ -1028,6 +1031,8 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc { int failureCode = InternalErrorException.STATUS_CODE; if (t instanceof BaseServerResponseException) { failureCode = ((BaseServerResponseException) t).getStatusCode(); + }else if(t instanceof java.lang.IllegalArgumentException && t.getMessage().contentEquals("The validated expression is false")) { + failureCode = Constants.STATUS_HTTP_400_BAD_REQUEST; } if (System.getProperty(UNIT_TEST_CAPTURE_STACK) != null) { diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java index 834d93ba816..fb33fcf46da 100644 --- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java +++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java @@ -7,7 +7,11 @@ import ca.uhn.fhir.parser.StrictErrorHandler; import ca.uhn.fhir.rest.api.CacheControlDirective; import ca.uhn.fhir.rest.api.Constants; import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor; +import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; +import com.ctc.wstx.shaded.msv_core.verifier.jarv.Const; +import org.hl7.fhir.r4.model.Base; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.IdType; import org.hl7.fhir.r4.model.Patient; @@ -27,6 +31,7 @@ import static org.hamcrest.Matchers.lessThan; import static org.hamcrest.core.IsNot.not; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.fail; public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test { @@ -227,5 +232,32 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test { assertEquals(1, resp2.getEntry().size()); } + @Test + public void testProcedurePatient(){ + Bundle resp2 = myClient + .search() + .byUrl("Procedure") + .returnBundle(Bundle.class) + .execute(); + + BaseServerResponseException exception = assertThrows(BaseServerResponseException.class, () -> {myClient + .search() + .byUrl("Procedure?patient=") + .returnBundle(Bundle.class) + .execute();}); + + assertEquals(Constants.STATUS_HTTP_400_BAD_REQUEST, exception.getStatusCode()); + } + + @Test + public void testPatient(){ + BaseServerResponseException exception = assertThrows(BaseServerResponseException.class, () -> {myClient + .search() + .byUrl("Procedure?patient=") + .returnBundle(Bundle.class) + .execute();}); + + assertEquals(Constants.STATUS_HTTP_400_BAD_REQUEST, exception.getStatusCode()); + } } diff --git a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java index 4ad522cf3be..061531f4cc1 100644 --- a/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java +++ b/hapi-fhir-jpaserver-searchparam/src/main/java/ca/uhn/fhir/jpa/searchparam/SearchParameterMap.java @@ -396,11 +396,15 @@ public class SearchParameterMap implements Serializable { for (List nextValuesAndIn : nextValuesAndsIn) { List nextValuesOrsOut = new ArrayList<>(); + /* for (IQueryParameterType nextValueOrIn : nextValuesAndIn) { if (nextValueOrIn.getMissing() != null || isNotBlank(nextValueOrIn.getValueAsQueryToken(theCtx))) { nextValuesOrsOut.add(nextValueOrIn); } } + */ + + nextValuesOrsOut.addAll(nextValuesAndIn); nextValuesOrsOut.sort(new QueryParameterTypeComparator(theCtx));