Don't allow Content-Location header to dictate version for updates
This commit is contained in:
parent
150c865f68
commit
3c4c6f7925
|
@ -78,9 +78,7 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
||||||
private int getOperationStatus(MethodOutcome response) {
|
private int getOperationStatus(MethodOutcome response) {
|
||||||
switch (getRestOperationType()) {
|
switch (getRestOperationType()) {
|
||||||
case CREATE:
|
case CREATE:
|
||||||
if (response == null) {
|
validateResponseNotNullIfItShouldntBe(response);
|
||||||
throw new InternalErrorException("Method " + getMethod().getName() + " in type " + getMethod().getDeclaringClass().getCanonicalName() + " returned null, which is not allowed for create operation");
|
|
||||||
}
|
|
||||||
if (response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
|
if (response.getCreated() == null || Boolean.TRUE.equals(response.getCreated())) {
|
||||||
return Constants.STATUS_HTTP_201_CREATED;
|
return Constants.STATUS_HTTP_201_CREATED;
|
||||||
}
|
}
|
||||||
|
@ -95,10 +93,8 @@ abstract class BaseOutcomeReturningMethodBinding extends BaseMethodBinding<Metho
|
||||||
case VALIDATE:
|
case VALIDATE:
|
||||||
case DELETE:
|
case DELETE:
|
||||||
default:
|
default:
|
||||||
|
validateResponseNotNullIfItShouldntBe(response);
|
||||||
if (response == null) {
|
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;
|
return Constants.STATUS_HTTP_204_NO_CONTENT;
|
||||||
}
|
}
|
||||||
if (response.getOperationOutcome() == null) {
|
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
|
@Override
|
||||||
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
public boolean incomingServerRequestMatchesMethod(RequestDetails theRequest) {
|
||||||
Set<RequestTypeEnum> allowableRequestTypes = provideAllowableRequestTypes();
|
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);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,38 +49,13 @@ public class UpdateMethodBinding extends BaseOutcomeReturningMethodBindingWithRe
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addParametersForServerRequest(RequestDetails theRequest, Object[] theParams) {
|
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();
|
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);
|
id = applyETagAsVersion(theRequest, id);
|
||||||
|
|
||||||
if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
|
if (theRequest.getId() != null && theRequest.getId().hasVersionIdPart() == false) {
|
||||||
if (id != null && id.hasVersionIdPart()) {
|
if (id != null && id.hasVersionIdPart()) {
|
||||||
theRequest.getId().setValue(id.getValue());
|
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);
|
super.addParametersForServerRequest(theRequest, theParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -334,6 +334,12 @@
|
||||||
The JPA server did not correctly process _has queries where the linked search parameter was
|
The JPA server did not correctly process _has queries where the linked search parameter was
|
||||||
the _id parameter.
|
the _id parameter.
|
||||||
</action>
|
</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>
|
||||||
<release version="4.0.3" date="2019-09-03" description="Igloo (Point Release)">
|
<release version="4.0.3" date="2019-09-03" description="Igloo (Point Release)">
|
||||||
<action type="fix">
|
<action type="fix">
|
||||||
|
|
Loading…
Reference in New Issue