Respect response status code set in MethodOutcome of a Resource provider (#5267)

* failing test

* fix

* extract response code modifying resource provider for testing

* comment

* remove TestResponseCodeModifyingPatientProvider
This commit is contained in:
Nathan Doef 2023-08-31 14:08:45 -04:00 committed by GitHub
parent 590e6ba88f
commit cc283b7732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 95 additions and 2 deletions

View File

@ -40,7 +40,7 @@ public class MethodOutcome {
private IBaseResource myResource; private IBaseResource myResource;
private Map<String, List<String>> myResponseHeaders; private Map<String, List<String>> myResponseHeaders;
private Collection<Runnable> myResourceViewCallbacks; private Collection<Runnable> myResourceViewCallbacks;
private int myResponseStatusCode; private Integer myResponseStatusCode;
/** /**
* Constructor * Constructor
@ -258,6 +258,10 @@ public class MethodOutcome {
} }
public int getResponseStatusCode() { public int getResponseStatusCode() {
return myResponseStatusCode; return isResponseStatusCodeSet() ? myResponseStatusCode : 0;
}
public boolean isResponseStatusCodeSet() {
return myResponseStatusCode != null;
} }
} }

View File

@ -544,6 +544,7 @@ public class MethodUtil {
} }
MethodOutcome retVal = new MethodOutcome(); MethodOutcome retVal = new MethodOutcome();
retVal.setResponseStatusCode(theResponseStatusCode);
if (locationHeaders.size() > 0) { if (locationHeaders.size() > 0) {
String locationHeader = locationHeaders.get(0); String locationHeader = locationHeaders.get(0);
BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, locationHeader); BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, locationHeader);

View File

@ -0,0 +1,5 @@
---
type: fix
issue: 5268
title: "Previously, the response status code set in a `MethodOutcome` of a Resource provider was not respected.
This has been fixed."

View File

@ -80,6 +80,12 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding {
protected abstract String getMatchingOperation(); protected abstract String getMatchingOperation();
private int getOperationStatus(MethodOutcome response) { private int getOperationStatus(MethodOutcome response) {
// if the response status code is set (i.e. from a custom Resource provider) it should be respected
if (response.isResponseStatusCodeSet()) {
return response.getResponseStatusCode();
}
switch (getRestOperationType()) { switch (getRestOperationType()) {
case CREATE: case CREATE:
validateResponseNotNullIfItShouldntBe(response); validateResponseNotNullIfItShouldntBe(response);

View File

@ -0,0 +1,77 @@
package ca.uhn.fhir.rest.server;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.client.api.IGenericClient;
import ca.uhn.fhir.test.utilities.server.RestfulServerExtension;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.IdType;
import org.hl7.fhir.r4.model.Patient;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import javax.servlet.ServletRequest;
import static ca.uhn.fhir.rest.api.Constants.STATUS_HTTP_202_ACCEPTED;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class ResponseCodeModifyingResourceProviderTest {
public static final int CUSTOM_RESPONSE_CODE = STATUS_HTTP_202_ACCEPTED;
@RegisterExtension
private RestfulServerExtension myServer = new RestfulServerExtension(FhirVersionEnum.R4)
.registerProvider(new TestResponseCodeModifyingPatientProvider());
private IGenericClient myClient;
private Patient myPatient;
@BeforeEach
public void before() {
myPatient = new Patient();
myPatient.getNameFirstRep().addGiven("John").setFamily("Smith");
myClient = myServer.getFhirClient();
}
@Test
public void testCreatePatientReturnsModifiedResponseCode() {
MethodOutcome outcome = myClient.create().resource(myPatient).execute();
assertEquals(CUSTOM_RESPONSE_CODE, outcome.getResponseStatusCode());
}
@Test
public void testUpdatePatientReturnsModifiedResponseCode() {
myPatient.setId("1");
MethodOutcome outcome = myClient.update().resource(myPatient).execute();
assertEquals(CUSTOM_RESPONSE_CODE, outcome.getResponseStatusCode());
}
class TestResponseCodeModifyingPatientProvider implements IResourceProvider {
@Create()
public MethodOutcome createPatient(@ResourceParam Patient thePatient, ServletRequest theServletRequest) {
MethodOutcome methodOutcome = new MethodOutcome();
methodOutcome.setResponseStatusCode(CUSTOM_RESPONSE_CODE);
return methodOutcome;
}
@Update()
public MethodOutcome updatePatient(@IdParam IdType theId, @ResourceParam Patient thePatient) {
MethodOutcome methodOutcome = new MethodOutcome();
methodOutcome.setResponseStatusCode(CUSTOM_RESPONSE_CODE);
return methodOutcome;
}
@Override
public Class<? extends IBaseResource> getResourceType() {
return Patient.class;
}
}
}