Don't allow Content-Location header to dictate version for updates

This commit is contained in:
James Agnew 2019-10-04 09:55:14 -04:00
parent 150c865f68
commit 3c4c6f7925
3 changed files with 14 additions and 41 deletions

View File

@ -78,9 +78,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
private int getOperationStatus(MethodOutcome response) {
switch (getRestOperationType()) {
case CREATE:
if (response == null) {
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null, which is not allowed for create operation");
}
validateResponseNotNullIfItShouldntBe(response);
if (response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
return Constants.STATUS_HTTP_201_CREATED;
}
@ -95,10 +93,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
case VALIDATE:
case DELETE:
default:
validateResponseNotNullIfItShouldntBe(response);
if (response == null) {
if (isReturnVoid() == false) {
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
}
return Constants.STATUS_HTTP_204_NO_CONTENT;
}
if (response.getOperationOutcome() == null) {
@ -108,6 +104,12 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
}
}
private void validateResponseNotNullIfItShouldntBe(MethodOutcome response) {
if (response == null && !isReturnVoid()) {
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null");
}
}
@Override
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
Set<RequestTypeEnum> allowableRequestTypes = provideAllowableRequestTypes();
@ -239,14 +241,4 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
return restfulResponse.streamResponseAsResource(responseDetails.getResponseResource(), prettyPrint, summaryMode, responseDetails.getResponseCode(), null, theRequest.isRespondGzip(), true);
}
protected static void parseContentLocation(FhirContext theContext, MethodOutcome theOutcomeToPopulate, String theLocationHeader) {
if (StringUtils.isBlank(theLocationHeader)) {
return;
}
IIdType id = theContext.getVersion().newIdType();
id.setValue(theLocationHeader);
theOutcomeToPopulate.setId(id);
}
}

View File

@ -49,38 +49,13 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
@Override
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
/*
* We are being a bit lenient here, since technically the client is supposed to include the version in the
* Content-Location header, but we allow it in the PUT URL as well..
*/
String locationHeader = theRequest.getHeader(Constants.HEADER_CONTENT_LOCATION);
IIdType id = theRequest.getId();
if (isNotBlank(locationHeader)) {
id.setValue(locationHeader);
if (isNotBlank(id.getResourceType())) {
if (!getResourceName().equals(id.getResourceType())) {
throw new InvalidRequestException(
"Attempting to update '" + getResourceName() + "' but content-location header specifies different resource type '" + id.getResourceType() + "' - header value: " + locationHeader);
}
}
}
id = applyETagAsVersion(theRequest, id);
if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
if (id != null && id.hasVersionIdPart()) {
theRequest.getId().setValue(id.getValue());
}
}
if (isNotBlank(locationHeader)) {
MethodOutcome mo = new MethodOutcome();
parseContentLocation(getContext(), mo, locationHeader);
if (mo.getId() == null || mo.getId().isEmpty()) {
throw new InvalidRequestException("Invalid Content-Location header for resource " + getResourceName() + ": " + locationHeader);
}
}
super.addParametersForServerRequest(theRequest, theParams);
}

View File

@ -334,6 +334,12 @@
The JPA server did not correctly process _has queries where the linked search parameter was
the _id parameter.
</action>
<action type="remove">
HTTP PUT (resource update) operations will no longer allow the version to be specified in a
Content-Location header. This behaviour was allowed in DSTU1 and was never removed from HAPI even though
it hasn't been permitted in the spec for a very long time. Hopefully this change will not
impact anyone!
</action>
</release>
<release version="4.0.3" date="2019-09-03" description="Igloo (Point Release)">
<action type="fix">