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

Feature/480 FhirClient implementation with HttpClient #507

Merged

Conversation

Devereux-Henley
Copy link

  • Created new implementation of FhirClient using System.Net.Http.HttpClient.
  • New mirrored classes placed in Hl7.Fhir.Rest.Http namespace
  • Common functionality extracted to a base class.
  • Old implementation marked as [Obsolete]
  • FhirClient now IDisposable
  • Simply swapping classes will compile, throw exceptions on obsoleted functionality.

Henley_Contractor, Devereux added 30 commits November 20, 2017 15:46
@ewoutkramer
Copy link
Member

Thanks! That's a major chunk of work. I will need some time to digest it ;-)

Copy link
Member

@ewoutkramer ewoutkramer left a comment

Choose a reason for hiding this comment

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

Really nice piece of work! Pls review my comments, then I'll pull it as a feature branch!

result.Response.Location = response.Headers.Location?.AbsoluteUri ?? response.Content.Headers.ContentLocation?.AbsoluteUri;

result.Response.LastModified = response.Content.Headers.LastModified;
result.Response.Etag = response.Headers.ETag?.Tag;
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this does 100% what getEtag() did in the original code: the result.Response.Etag will now be set to include the quotes around the etag, while getEtag() removed those (result = result.Trim('\"')).

Copy link
Author

Choose a reason for hiding this comment

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

Will restore trim.

{
result.Response.SetBody(body);

if (Rest.HttpToEntryExtensions.IsBinaryResponse(result.Response.Location, contentType.ToString()))
Copy link
Member

Choose a reason for hiding this comment

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

I think this must be contentType.MediaType, since otherwise it might include the charset parameter, which was removed by the original code using getContentType().

Copy link
Author

Choose a reason for hiding this comment

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

Will replace with MediaType


if (Rest.HttpToEntryExtensions.IsBinaryResponse(result.Response.Location, contentType.ToString()))
{
result.Resource = Rest.HttpToEntryExtensions.MakeBinaryResource(body, contentType.ToString());
Copy link
Member

Choose a reason for hiding this comment

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

This is actually better than the original, since it will include the charset parameter, which the original code did not.

else
{
var bodyText = Rest.HttpToEntryExtensions.DecodeBody(body, charEncoding);
var resource = Rest.HttpToEntryExtensions.ParseResource(bodyText, contentType.ToString(), parserSettings, throwOnFormatException);
Copy link
Member

Choose a reason for hiding this comment

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

Also here, contentType.ToString() would include the charset parameter (if the client passed that in), which will not work well with DecodeBody, I think this should be contentType.MediaType

Copy link
Author

Choose a reason for hiding this comment

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

Will change to MediaType.

var request = new HttpRequestMessage(getMethod(interaction.Method), location.Uri);

if (!useFormatParameter)
request.Headers.Add("Accept", Hl7.Fhir.Rest.ContentType.BuildContentType(format, forBundle: false));
Copy link
Member

Choose a reason for hiding this comment

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

What is the reason you are not doing request.Headers.Accept.Add()?

Copy link
Author

Choose a reason for hiding this comment

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

Did not see static MediaTypeWithQualityHeaderValue.Parse. Replaced this with a call to request.Headers.Accept.Add.

if (!useFormatParameter)
request.Headers.Add("Accept", Hl7.Fhir.Rest.ContentType.BuildContentType(format, forBundle: false));

if (interaction.IfMatch != null) request.Headers.TryAddWithoutValidation("If-Match", interaction.IfMatch);
Copy link
Member

Choose a reason for hiding this comment

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

Is the way we use If-Match in FHIR illegal, so we need to avoid validation?

Copy link
Author

Choose a reason for hiding this comment

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

No. This was added while debugging and is no longer needed. Will replace with Add.


request.Content = new ByteArrayContent(body);

// MediaTypeHeaderValue cannot accept a content type that contains charset at the end, so that value must be split out.
Copy link
Member

Choose a reason for hiding this comment

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

Yes, I noticed the same, weird. Maybe I'll take a look at the reference source to see why.

Copy link
Member

Choose a reason for hiding this comment

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

If you look at https://github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/System/Net/Http/Headers/MediaTypeHeaderValue.cs#L203, it seems there is support for parsing mediatypes with parameters...

Copy link
Author

Choose a reason for hiding this comment

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

Will replace with MediaTypeHeaderValue.Parse(contentType)


namespace Hl7.Fhir.Core.Tests.Rest.Mocks
{
public class MockHttpMessageHandler : HttpClientHandler
Copy link
Member

Choose a reason for hiding this comment

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

This MessageHandler could be used by people who want to still use the OnBefore/OnAfter logic, right? The name "mock" did not suggest that to me (I would think it has something to do with testing). Maybe call it "RequestResponseEventMessageHandler" or something like that?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, this is actually there to support testing ;-) But we could provide it more generally, as I mentioned, right?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, this could be provided more generally. I will move this to the new namespace and rename.

@ewoutkramer ewoutkramer changed the base branch from develop-stu3 to feature/480-httpclient December 13, 2017 16:51
@ewoutkramer ewoutkramer merged commit 70ec9b0 into FirelyTeam:feature/480-httpclient Dec 13, 2017
@mmsmits
Copy link
Member

mmsmits commented Jun 18, 2020

@Devereux-Henley Thanks so much for all your efforts on this. We have re-used a lot of your code, in a separate PR which now has (finally) been merged into develop-r4 and develop-stu3. If you like, please take a look to see if you like how we implemented it. We would appreciate your feedback very much. Hope you like it! Thanks again!

@mmsmits mmsmits self-requested a review June 18, 2020 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants