Skip to content

Commit

Permalink
issue #3242 - get fhirVersion from Content-Type for create/update
Browse files Browse the repository at this point in the history
Previously I was only looking in the Accept header. Now, for PUT and
POST requests, I'll check the Content-Type header first.

Signed-off-by: Lee Surprenant <lmsurpre@us.ibm.com>
  • Loading branch information
lmsurpre committed Mar 9, 2022
1 parent c00890c commit e09fd9e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 13 deletions.
2 changes: 2 additions & 0 deletions fhir-core/src/main/java/com/ibm/fhir/core/FHIRMediaType.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class FHIRMediaType extends MediaType {
// Supported values for the MIME-type parameter fhirVersion.
// https://www.hl7.org/fhir/http.html#version-parameter
public static final String FHIR_VERSION_PARAMETER = "fhirVersion";
public static final Set<String> ADVERTISED_FHIR_VERSIONS =
Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(VERSION_40, VERSION_43)));
public static final Set<String> SUPPORTED_FHIR_VERSIONS =
Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(VERSION_40, VERSION_401, VERSION_43, VERSION_430)));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ void checkFhirVersionParameter(FHIRRequestContext context) throws FHIRRestServle
if (curFhirVersion != null && !FHIRMediaType.SUPPORTED_FHIR_VERSIONS.contains(curFhirVersion)) {
throw new FHIRRestServletRequestException("Invalid '" + FHIRMediaType.FHIR_VERSION_PARAMETER
+ "' parameter value in '" + headerName + "' header; the following FHIR versions are supported: "
+ FHIRMediaType.SUPPORTED_FHIR_VERSIONS, headerStatusMap.get(headerName));
+ FHIRMediaType.ADVERTISED_FHIR_VERSIONS, headerStatusMap.get(headerName));
}
// If Content-Type header, check for multiple different FHIR versions
if (headerName.equalsIgnoreCase(HttpHeaders.CONTENT_TYPE)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import java.io.IOException;

import javax.ws.rs.HttpMethod;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.MediaType;
Expand All @@ -20,27 +21,82 @@
import com.ibm.fhir.core.FHIRMediaType;
import com.ibm.fhir.core.FHIRVersionParam;

/**
* A request filter that sets the {@value #FHIR_VERSION_PROP} request context property with the
* preferred FHIRVersionParam for the current interaction according to the following algorithm:
*
* <p>For PUT and POST requests:
* <ol>
* <li>if the Content-Type header has a proper fhirVersion value (e.g. "4.0" or "4.3") use that
* <li>otherwise fall back to the "other request" algorithm
* </ol>
* <p>For all other requests:
* <ol>
* <li>"4.3" from the acceptableMediaTypes
* <li>"4.0" from the acceptableMediaTypes
* <li>whatever is configured in the fhirServer/core/defaultFhirVersion config property
* <li>"4.0"
* </ol>
*/
public class FHIRVersionRequestFilter implements ContainerRequestFilter {
public static final String FHIR_VERSION_PROP = "com.ibm.fhir.server.fhirVersion";

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
/*
* This method will look through the MediaTypes constructed by JAX-RS from the incoming "Accept" header
* and add the most preferred value to the request context under the FHIR_VERSION_PROP name using the following
* order of preference:
*
* 1. "4.3" from the acceptableMediaTypes
* 2. "4.0" from the acceptableMediaTypes
* 3. whatever is configured in the fhirServer/core/defaultFhirVersion config property
* 4. "4.0"
*/
FHIRVersionParam fhirVersion;

switch (requestContext.getMethod()) {
case HttpMethod.POST:
case HttpMethod.PUT:
fhirVersion = getFhirVersionFromContentTypeHeader(requestContext);
break;
case HttpMethod.GET:
default:
fhirVersion = getFhirVersionFromAcceptHeader(requestContext);
break;
}

requestContext.setProperty(FHIR_VERSION_PROP, fhirVersion);
}

/**
* The FHIRVersionParam to use for the current interaction as determined by the Content-Type header
*
* @param requestContext
* @return the FHIRVersionParam value from the Content-Type header if it is specified,
* otherwise falls back to {@link #getFhirVersionFromAcceptHeader(ContainerRequestContext)}
*/
private FHIRVersionParam getFhirVersionFromContentTypeHeader(ContainerRequestContext requestContext) {
MediaType mediaType = requestContext.getMediaType();
if (mediaType != null) {
String submittedVersion = mediaType.getParameters().get(FHIRMediaType.FHIR_VERSION_PARAMETER);
if (submittedVersion != null) {
// "startsWith" to cover the x.y.z cases which are technically invalid, but close enough
if (submittedVersion.startsWith(VERSION_43.value())) {
return VERSION_43;
} else if (submittedVersion.startsWith(VERSION_40.value())) {
return VERSION_40;
}
}
}
// fall back to getFhirVersionFromAcceptHeader logic
return getFhirVersionFromAcceptHeader(requestContext);
}

/**
* The FHIRVersionParam to use for the current interaction as determined by the Accept header
*
* @param requestContext
* @return the FHIRVersionParam value from the Accept header if it is specified,
* otherwise from the defaultFhirVersion property of the fhir-server-config
*/
private FHIRVersionParam getFhirVersionFromAcceptHeader(ContainerRequestContext requestContext) {
FHIRVersionParam fhirVersion = null;
for (MediaType mediaType : requestContext.getAcceptableMediaTypes()) {
if (mediaType.getParameters() != null) {
String fhirVersionParam = mediaType.getParameters().get(FHIRMediaType.FHIR_VERSION_PARAMETER);
if (fhirVersionParam != null) {
// "startsWith" to cover the x.y.x cases which are technically invalid, but close enough
// "startsWith" to cover the x.y.z cases which are technically invalid, but close enough
if (fhirVersionParam.startsWith(VERSION_43.value())) {
// one of the acceptable media types was our "actual" fhir version, so use that and stop looking
fhirVersion = VERSION_43;
Expand All @@ -56,6 +112,6 @@ public void filter(ContainerRequestContext requestContext) throws IOException {
String fhirVersionString = FHIRConfigHelper.getStringProperty(FHIRConfiguration.PROPERTY_DEFAULT_FHIR_VERSION, VERSION_40.value());
fhirVersion = FHIRVersionParam.from(fhirVersionString);
}
requestContext.setProperty(FHIR_VERSION_PROP, fhirVersion);
return fhirVersion;
}
}

0 comments on commit e09fd9e

Please sign in to comment.