Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support providing the HttpClient direct to the FhirClient #2049

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common
90 changes: 89 additions & 1 deletion src/Hl7.Fhir.Core.Tests/Rest/FhirClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1385,7 +1385,7 @@ public void CallsCallbacksWebClient()

[TestMethod]
[TestCategory("FhirClient"), TestCategory("IntegrationTest")]
public void CallsCallbacksHttpClient()
public void CallsCallbacksHttpClientHandler()
{
using (var handler = new HttpClientEventHandler())
{
Expand Down Expand Up @@ -1470,6 +1470,94 @@ public void CallsCallbacksHttpClient()
}
}

[TestMethod]
[TestCategory("FhirClient"), TestCategory("IntegrationTest")]
public void CallsCallbacksHttpClient()
{
using (var handler = new HttpClientEventHandler())
using (var httpClient = new HttpClient(handler))
{
using (FhirClient client = new FhirClient(testEndpoint, httpClient: httpClient))
{
client.Settings.ParserSettings.AllowUnrecognizedEnums = true;

bool calledBefore = false;
HttpStatusCode? status = null;
byte[] body = null;
byte[] bodyOut = null;

handler.OnBeforeRequest += (sender, e) =>
{
calledBefore = true;
bodyOut = e.Body;
};

handler.OnAfterResponse += (sender, e) =>
{
body = e.Body;
status = e.RawResponse.StatusCode;
};

var pat = client.Read<Patient>("Patient/" + patientId);
Assert.IsTrue(calledBefore);
Assert.IsNotNull(status);
Assert.IsNotNull(body);

var bodyText = HttpUtil.DecodeBody(body, Encoding.UTF8);

Assert.IsTrue(bodyText.Contains("<Patient"));

calledBefore = false;
client.Update(pat); // create cannot be called with an ID (which was retrieved)
Assert.IsTrue(calledBefore);
Assert.IsNotNull(bodyOut);

bodyText = HttpUtil.DecodeBody(body, Encoding.UTF8);
Assert.IsTrue(bodyText.Contains("<Patient"));
}

// And use another on the same handler to ensure that it wasn't disposed :O
using (FhirClient client = new FhirClient(testEndpoint, httpClient: httpClient))
{
client.Settings.ParserSettings.AllowUnrecognizedEnums = true;

bool calledBefore = false;
HttpStatusCode? status = null;
byte[] body = null;
byte[] bodyOut = null;

handler.OnBeforeRequest += (sender, e) =>
{
calledBefore = true;
bodyOut = e.Body;
};

handler.OnAfterResponse += (sender, e) =>
{
body = e.Body;
status = e.RawResponse.StatusCode;
};

var pat = client.Read<Patient>("Patient/" + patientId);
Assert.IsTrue(calledBefore);
Assert.IsNotNull(status);
Assert.IsNotNull(body);

var bodyText = HttpUtil.DecodeBody(body, Encoding.UTF8);

Assert.IsTrue(bodyText.Contains("<Patient"));

calledBefore = false;
client.Update(pat); // create cannot be called with an ID (which was retrieved)
Assert.IsTrue(calledBefore);
Assert.IsNotNull(bodyOut);

bodyText = HttpUtil.DecodeBody(body, Encoding.UTF8);
Assert.IsTrue(bodyText.Contains("<Patient"));
}
}
}

//[TestMethod]
//public void TestBinaryDetection()
//{
Expand Down
51 changes: 45 additions & 6 deletions src/Hl7.Fhir.Core/Rest/FhirClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* available at https://raw.githubusercontent.com/FirelyTeam/firely-net-sdk/master/LICENSE
*/

using Hl7.Fhir.Model;
using Hl7.Fhir.Serialization;
using Hl7.Fhir.Specification;
using System;
Expand All @@ -19,15 +18,16 @@ namespace Hl7.Fhir.Rest
{
public partial class FhirClient : BaseFhirClient
{
//disables warning that OnBeforeRequest and OnAfterResponse are never used.
//disables warning that OnBeforeRequest and OnAfterResponse are never used.
#pragma warning disable CS0067

/// <summary>
/// Creates a new client using a default endpoint
/// If the endpoint does not end with a slash (/), it will be added.
/// </summary>
/// <remarks>
/// If the messageHandler is provided then it must be disposed by the caller
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the messageHandler is provided then it must be disposed by the caller
Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the messageHandler is provided then it must be disposed by the caller
Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller

/// Only one of the messageHandler or httpClient can be provided
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Only one of the messageHandler or httpClient can be provided
Suggested change
/// Only one of the messageHandler or httpClient can be provided
/// Only one of the messageHandler or httpClient can be provided

brianpos marked this conversation as resolved.
Show resolved Hide resolved
/// </remarks>
/// <param name="endpoint">
/// The URL of the server to connect to.<br/>
Expand All @@ -38,19 +38,42 @@ public partial class FhirClient : BaseFhirClient
/// <param name="provider"></param>
public FhirClient(Uri endpoint, FhirClientSettings settings = null, HttpMessageHandler messageHandler = null, IStructureDefinitionSummaryProvider provider = null) : base(endpoint, settings, provider)
{
// If user does not supply message handler, add decompression strategy in default handler.
// If user does not supply message handler, create our own and add decompression strategy in default handler.
var handler = messageHandler ?? new HttpClientHandler()
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};

var requester = new HttpClientRequester(Endpoint, Settings, handler, messageHandler == null);
HttpClientRequester requester = new HttpClientRequester(Endpoint, Settings, handler, messageHandler == null);
Requester = requester;

// Expose default request headers to user.
RequestHeaders = requester.Client.DefaultRequestHeaders;
}

/// <summary>
/// Creates a new client using a default endpoint
/// If the endpoint does not end with a slash (/), it will be added.
/// </summary>
/// <remarks>
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the httpClient is provided then it must be disposed by the caller
Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the httpClient is provided then it must be disposed by the caller
Suggested change
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller
/// If the messageHandler, or httpClient is provided then it must be disposed by the caller

/// Only one of the messageHandler or httpClient can be provided
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Only one of the messageHandler or httpClient can be provided
Suggested change
/// Only one of the messageHandler or httpClient can be provided
/// Only one of the messageHandler or httpClient can be provided

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Only one of the messageHandler or httpClient can be provided
Suggested change
/// Only one of the messageHandler or httpClient can be provided
/// Only one of the messageHandler or httpClient can be provided

/// </remarks>
/// <param name="endpoint">
/// The URL of the server to connect to.<br/>
/// If the trailing '/' is not present, then it will be appended automatically
/// </param>
/// <param name="settings"></param>
/// <param name="httpClient"></param>
/// <param name="provider"></param>
public FhirClient(Uri endpoint, HttpClient httpClient, FhirClientSettings settings = null, IStructureDefinitionSummaryProvider provider = null) : base(endpoint, settings, provider)
{
HttpClientRequester requester = new HttpClientRequester(Endpoint, Settings, httpClient);
Requester = requester;

// Expose default request headers to user.
RequestHeaders = requester.Client.DefaultRequestHeaders;
}

/// <summary>
/// Creates a new client using a default endpoint
Expand All @@ -68,6 +91,22 @@ public FhirClient(string endpoint, FhirClientSettings settings = null, HttpMessa
{
}

/// <summary>
/// Creates a new client using a default endpoint
/// If the endpoint does not end with a slash (/), it will be added.
/// </summary>
/// <param name="endpoint">
/// The URL of the server to connect to.<br/>
/// If the trailing '/' is not present, then it will be appended automatically
/// </param>
/// <param name="settings"></param>
/// <param name="httpClient"></param>
/// <param name="provider"></param>
public FhirClient(string endpoint, HttpClient httpClient, FhirClientSettings settings = null, IStructureDefinitionSummaryProvider provider = null)
: this(new Uri(endpoint), httpClient, settings, provider)
{
}

/// <summary>
/// Default request headers that can be modified to persist default headers to internal client.
/// </summary>
Expand Down Expand Up @@ -178,7 +217,7 @@ public ParserSettings ParserSettings
}
#endregion

[Obsolete ("OnBeforeRequest is deprecated, please add a HttpClientEventHandler or another HttpMessageHandler to the constructor to use this functionality", true)]
[Obsolete("OnBeforeRequest is deprecated, please add a HttpClientEventHandler or another HttpMessageHandler to the constructor to use this functionality", true)]
public event EventHandler<BeforeHttpRequestEventArgs> OnBeforeRequest;

[Obsolete("OnAfterResponse is deprecated, please add a HttpClientEventHandler or another HttpMessageHandler to the constructor to use this functionality", true)]
Expand Down