diff --git a/src/Hl7.Fhir.Base/Rest/BaseFhirClient.cs b/src/Hl7.Fhir.Base/Rest/BaseFhirClient.cs
index ed092fb444..251825a6ba 100644
--- a/src/Hl7.Fhir.Base/Rest/BaseFhirClient.cs
+++ b/src/Hl7.Fhir.Base/Rest/BaseFhirClient.cs
@@ -11,6 +11,7 @@
using Hl7.Fhir.Introspection;
using Hl7.Fhir.Model;
using Hl7.Fhir.Serialization;
+using Hl7.Fhir.Specification;
using Hl7.Fhir.Utility;
using System;
using System.Collections.Generic;
@@ -860,9 +861,9 @@ private static ResourceIdentity verifyResourceIdentity(Uri location, bool needId
if (msg is null && entryComponent is null) throw new ArgumentException("Either msg or entryComponent should be set");
// Validate the response and throw the appropriate exceptions. Also, if we have *not* verified the FHIR version
// of the server, add a suggestion about this in the (legacy) parsing exception.
- var suggestedVersionOnParseError = !Settings.VerifyFhirVersion ? fhirVersion : null;
+
(LastResult, LastBody, LastBodyAsText, LastBodyAsResource, var issue) =
- await ValidateResponse(responseMessage, expect, getSerializationEngine(), suggestedVersionOnParseError, useBinaryProtocol)
+ await ValidateResponse(responseMessage, expect, getSerializationEngine(), !Settings.VerifyFhirVersion, fhirVersion, useBinaryProtocol)
.ConfigureAwait(false);
// If an error occurred while trying to interpret and validate the response, we will bail out now.
@@ -921,17 +922,20 @@ static string unexpectedBodyTypeForMessage(HttpRequestMessage msg, Resource resu
/// The body content type could not be handled or the response status indicated failure, or we received an unexpected success status.
/// Thrown when the original ITypedElement-based parsers are used and a parse exception occurred.
/// Thrown when a newer parsers is used and a parse exception occurred.
- ///
+ ///
internal static async Task ValidateResponse(
HttpResponseMessage responseMessage,
IEnumerable expect,
IFhirSerializationEngine engine,
- string? suggestedVersionOnParseError,
+ bool suggestVersionOnParsingError,
+ string fhirVersion,
bool useBinaryProtocol)
{
- var responseData = (await responseMessage.ExtractResponseData(engine, useBinaryProtocol).ConfigureAwait(false))
+ var fhirRelease = FhirReleaseParser.Parse(fhirVersion);
+
+ var responseData = (await responseMessage.ExtractResponseData(engine, useBinaryProtocol, fhirRelease).ConfigureAwait(false))
.TranslateUnsupportedBodyTypeException(responseMessage.StatusCode)
- .TranslateLegacyParserException(suggestedVersionOnParseError);
+ .TranslateLegacyParserException(suggestVersionOnParsingError ? fhirVersion : null);
// If extracting the data caused an issue, return it immediately
if (responseData.Issue is not null)
diff --git a/src/Hl7.Fhir.Base/Rest/HttpContentParsers.cs b/src/Hl7.Fhir.Base/Rest/HttpContentParsers.cs
index 38caf8be35..b237858f1b 100644
--- a/src/Hl7.Fhir.Base/Rest/HttpContentParsers.cs
+++ b/src/Hl7.Fhir.Base/Rest/HttpContentParsers.cs
@@ -11,6 +11,7 @@
using Hl7.Fhir.ElementModel;
using Hl7.Fhir.Model;
using Hl7.Fhir.Serialization;
+using Hl7.Fhir.Specification;
using Hl7.Fhir.Utility;
using System;
using System.Linq;
@@ -147,7 +148,7 @@ internal record ResponseData(Bundle.ResponseComponent Response, byte[]? BodyData
/// If the status of the response indicates failure, this function will be lenient and return the body data
/// instead of throwing an when the content type or content itself is not recognizable as FHIR. This improves
/// the chances of capturing diagnostic (non-FHIR) bodies returned by the server when an operation fails.
- internal static async Task ExtractResponseData(this HttpResponseMessage message, IFhirSerializationEngine ser, bool expectBinaryProtocol)
+ internal static async Task ExtractResponseData(this HttpResponseMessage message, IFhirSerializationEngine ser, bool expectBinaryProtocol, FhirRelease fhirRelease)
{
var component = message.ExtractResponseComponent();
var data = await message.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
@@ -159,14 +160,14 @@ internal static async Task ExtractResponseData(this HttpResponseMe
// If this is not binary data, try to capture the body as text
if (!expectBinaryProtocol)
result = result with { BodyText = await message.Content.GetBodyAsString().ConfigureAwait(false) };
-
+
var usesFhirFormat = ContentType.GetResourceFormatFromContentType(message.Content.GetContentType()) != ResourceFormat.Unknown;
try
{
var resource = message switch
{
- { IsSuccessStatusCode: true } when expectBinaryProtocol && !usesFhirFormat => await ReadBinaryDataFromMessage(message).ConfigureAwait(false),
+ { IsSuccessStatusCode: true } when expectBinaryProtocol && !usesFhirFormat => await ReadBinaryDataFromMessage(message, fhirRelease).ConfigureAwait(false),
{ IsSuccessStatusCode: true } => await ReadResourceFromMessage(message.Content, ser).ConfigureAwait(false),
{ IsSuccessStatusCode: false } => await ReadOutcomeFromMessage(message.Content, ser).ConfigureAwait(false),
};
@@ -179,7 +180,7 @@ internal static async Task ExtractResponseData(this HttpResponseMe
}
// Sets the Resource.ResourceBase to the location given in the RequestUri of the response message.
- if (result.BodyResource is not null && (message.Headers.Location?.OriginalString ?? message.GetRequestUri()?.OriginalString) is {} location)
+ if (result.BodyResource is not null && (message.Headers.Location?.OriginalString ?? message.GetRequestUri()?.OriginalString) is { } location)
{
var ri = new ResourceIdentity(location);
result.BodyResource.ResourceBase = ri.HasBaseUri && ri.Form == ResourceIdentityForm.AbsoluteRestUrl
@@ -196,11 +197,15 @@ internal static async Task ExtractResponseData(this HttpResponseMe
///
/// A resource containing the streamed binary data. The resource's
/// metadata will be retrieved from the appropriate HTTP headers.
- public static async Task ReadBinaryDataFromMessage(this HttpResponseMessage message)
+ public static async Task ReadBinaryDataFromMessage(this HttpResponseMessage message, FhirRelease fhirRelease)
{
var result = new Binary();
- result.Data = result.Content = await message.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
+ if (fhirRelease == FhirRelease.STU3)
+ result.Content = await message.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
+ else
+ result.Data = await message.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
+
result.ContentType = message.Content.GetContentType();
result.SecurityContext = message.GetSecurityContext() is { } reference ? new ResourceReference(reference) : null;
result.Meta ??= new();
diff --git a/src/Hl7.Fhir.Support.Poco.Tests/Rest/ResponseMessageTests.cs b/src/Hl7.Fhir.Support.Poco.Tests/Rest/ResponseMessageTests.cs
index 80ca9abdfd..88253ebbaf 100644
--- a/src/Hl7.Fhir.Support.Poco.Tests/Rest/ResponseMessageTests.cs
+++ b/src/Hl7.Fhir.Support.Poco.Tests/Rest/ResponseMessageTests.cs
@@ -101,7 +101,7 @@ public async Task SetAndExtractRelevantHeaders()
response.Headers.Location = new Uri("http://nu.nl");
response.Headers.TryAddWithoutValidation("Test-key", "Test-value");
- var extracted = await response.ExtractResponseData(engine, expectBinaryProtocol: false);
+ var extracted = await response.ExtractResponseData(engine, expectBinaryProtocol: false, TESTINSPECTOR.FhirRelease);
extracted.BodyText.Should().Be(DEFAULT_XML);
engine.SerializeToXml(extracted.BodyResource!).Should().Be(DEFAULT_XML);
@@ -117,7 +117,7 @@ public async Task SetAndExtractRelevantHeaders()
public async Task GetEmptyResponse()
{
var response = new HttpResponseMessage(HttpStatusCode.Conflict);
- var components = await response.ExtractResponseData(POCOENGINE, expectBinaryProtocol: false);
+ var components = await response.ExtractResponseData(POCOENGINE, expectBinaryProtocol: false, fhirRelease: Specification.FhirRelease.R4);
components.Response.Status.Should().Be("409");
components.BodyData.Should().BeNull();
@@ -128,7 +128,7 @@ public async Task GetEmptyResponse()
private static async Task check(HttpResponseMessage response, IFhirSerializationEngine engine,
bool hasResource = false, Type? expectedIssue = null, string? messagePattern = null, string? notMessagePattern = null)
{
- var components = await response.ExtractResponseData(engine, expectBinaryProtocol: false).ConfigureAwait(false);
+ var components = await response.ExtractResponseData(engine, expectBinaryProtocol: false, fhirRelease: Specification.FhirRelease.R4).ConfigureAwait(false);
await checkResult(response, components, engine, hasResource, expectedIssue, messagePattern, notMessagePattern);
}
@@ -299,7 +299,7 @@ await assertIssue(response, "Operation was unsuccessful,
public async Task TurnsNewParsingFailureIntoDFE()
{
var response = makeXmlMessage(xml: """""");
- await assertIssue(response, "*Unknown type 'Unknown' found in root property*", engine: POCOENGINE, version: "1.0.0");
+ await assertIssue(response, "*Unknown type 'Unknown' found in root property*", engine: POCOENGINE, suggestVersionOnParsingError: true, version: "1.0.0");
}
[TestMethod]
@@ -308,17 +308,17 @@ public async Task TurnsLegacyParsingFailureIntoFE()
var response = makeXmlMessage(xml: """""");
await assertIssue(response, "*Cannot locate type information for type 'Unknown'*", engine: ELEMENTENGINE, notmatch: "*with FHIR version 1.0.0*");
await assertIssue(response, "*Cannot locate type information for type 'Unknown'*" +
- "Are you connected to a FHIR server with FHIR version 1.0.0*", version: "1.0.0", engine: ELEMENTENGINE);
+ "Are you connected to a FHIR server with FHIR version 1.0.0*", true, version: "1.0.0", engine: ELEMENTENGINE);
response = makeJsonMessage(json: """{ "resourceType": "Patient", "activex": 4 }""");
await assertIssue(response, "*Encountered unknown element 'activex' at location*", engine: ELEMENTENGINE);
}
- private static async Task assertIssue(HttpResponseMessage response, string match, string? version = null,
+ private static async Task assertIssue(HttpResponseMessage response, string match, bool suggestVersionOnParsingError = false, string? version = null,
IFhirSerializationEngine? engine = null, string? notmatch = null)
where T : Exception
{
- var result = await BaseFhirClient.ValidateResponse(response, new[] { HttpStatusCode.OK }, engine ?? POCOENGINE, version, useBinaryProtocol: false);
+ var result = await BaseFhirClient.ValidateResponse(response, new[] { HttpStatusCode.OK }, engine ?? POCOENGINE, suggestVersionOnParsingError, (suggestVersionOnParsingError) ? version! : "1.0.0", useBinaryProtocol: false);
await checkResult(response, result, engine ?? POCOENGINE, hasResource: false, expectedIssue: typeof(T), messagePattern: match, notMessagePattern: notmatch);
}
@@ -336,15 +336,20 @@ public async Task GetBinaryBody()
msg.SetSecurityContext("http://nu.nl");
msg.SetVersionFromETag("123");
- var b = await msg.ReadBinaryDataFromMessage();
+ var b = await msg.ReadBinaryDataFromMessage(Specification.FhirRelease.R4);
- b.Content.Should().BeEquivalentTo(data);
+ b.Content.Should().BeNull();
b.Data.Should().BeEquivalentTo(data);
b.SecurityContext.Reference.Should().Be("http://nu.nl");
b.ContentType.Should().Be("application/crap");
b.Meta.VersionId.Should().Be("123");
b.Meta.LastUpdated.Should().Be(when);
b.Id.Should().Be("4");
+
+ b = await msg.ReadBinaryDataFromMessage(Specification.FhirRelease.STU3);
+ b.Content.Should().BeEquivalentTo(data);
+ b.Data.Should().BeNull();
+
}
}
}