Skip to content

Commit 9b16ea3

Browse files
committed
Engine: Support parsing the weak ETag representation
1 parent 7ff3ad2 commit 9b16ea3

File tree

3 files changed

+81
-36
lines changed

3 files changed

+81
-36
lines changed

src/Spark.Engine.Test/Extensions/HttpRequestFhirExtensionsTests.cs

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using System;
1010
using System.Net.Http;
1111
using Hl7.Fhir.Rest;
12+
using Microsoft.AspNetCore.Http;
13+
using Microsoft.Extensions.Primitives;
1214
using Spark.Engine.Utility;
1315
using System.Linq;
1416
using Xunit;
@@ -17,6 +19,78 @@ namespace Spark.Engine.Test.Extensions;
1719

1820
public class HttpRequestFhirExtensionsTests
1921
{
22+
[Theory]
23+
[InlineData("W/\"1\"", "1")]
24+
[InlineData("W/\"123\"", "123")]
25+
[InlineData("\"1\"", "1")]
26+
[InlineData("\"123\"", "123")]
27+
public void IfMatchVersionId_ShouldExtractVersionFromETag(string headerValue, string expectedVersionId)
28+
{
29+
var context = new DefaultHttpContext();
30+
context.Request.Headers.Add("If-Match", new StringValues(headerValue));
31+
32+
string actualVersionId = context.Request.IfMatchVersionId();
33+
34+
Assert.Equal(expectedVersionId, actualVersionId);
35+
}
36+
37+
[Fact]
38+
public void IfMatchVersionId_WithNoHeader_ShouldReturnNull()
39+
{
40+
var context = new DefaultHttpContext();
41+
42+
string actualVersionId = context.Request.IfMatchVersionId();
43+
44+
Assert.Null(actualVersionId);
45+
}
46+
47+
[Fact]
48+
public void IfMatchVersionId_WithEmptyHeaders_ShouldReturnNull()
49+
{
50+
var context = new DefaultHttpContext();
51+
context.Request.Headers.Add("If-Match", "");
52+
53+
string actualVersionId = context.Request.IfMatchVersionId();
54+
55+
Assert.Null(actualVersionId);
56+
}
57+
58+
[Theory]
59+
[InlineData("W/\"1\"", "1")]
60+
[InlineData("W/\"123\"", "123")]
61+
[InlineData("\"1\"", "1")]
62+
[InlineData("\"123\"", "123")]
63+
public void HttpRequestMessage_IfMatchVersionId_ShouldExtractVersionFromETag(string headerValue, string expectedVersionId)
64+
{
65+
var request = new HttpRequestMessage();
66+
request.Headers.Add("If-Match", headerValue);
67+
68+
string actualVersionId = request.IfMatchVersionId();
69+
70+
Assert.Equal(expectedVersionId, actualVersionId);
71+
}
72+
73+
[Fact]
74+
public void HttpRequestMessage_IfMatchVersionId_WithNoHeader_ShouldReturnNull()
75+
{
76+
var request = new HttpRequestMessage();
77+
78+
string actualVersionId = request.IfMatchVersionId();
79+
80+
Assert.Null(actualVersionId);
81+
}
82+
83+
[Fact]
84+
public void HttpRequestMessage_IfMatchVersionId_WithEmptyHeaders_ShouldReturnNull()
85+
{
86+
var request = new HttpRequestMessage();
87+
request.Headers.Add("If-Match", "");
88+
89+
string actualVersionId = request.IfMatchVersionId();
90+
91+
Assert.Null(actualVersionId);
92+
}
93+
2094
[Fact]
2195
public void TestGetDateParameter()
2296
{

src/Spark.Engine/Extensions/HttpRequestFhirExtensions.cs

Lines changed: 6 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,14 @@
2323
using Microsoft.AspNetCore.Http.Headers;
2424
using Microsoft.AspNetCore.Http;
2525
using Microsoft.Extensions.Primitives;
26+
using Microsoft.Net.Http.Headers;
2627
#endif
2728

2829
[assembly: InternalsVisibleTo("Spark.Engine.Test")]
2930
namespace Spark.Engine.Extensions;
3031

3132
public static class HttpRequestFhirExtensions
3233
{
33-
private static string WithoutQuotes(string s)
34-
{
35-
if (string.IsNullOrEmpty(s))
36-
{
37-
return null;
38-
}
39-
else
40-
{
41-
return s.Trim('"');
42-
}
43-
}
44-
4534
#if NETSTANDARD2_0 || NET6_0
4635
public static int GetPagingOffsetParameter(this HttpRequest request)
4736
{
@@ -77,12 +66,8 @@ internal static IEnumerable<string> IfNoneMatch(this HttpRequest request)
7766

7867
public static string IfMatchVersionId(this HttpRequest request)
7968
{
80-
if (request.Headers.Count == 0) return null;
81-
82-
if (!request.Headers.TryGetValue("If-Match", out StringValues value)) return null;
83-
var tag = value.FirstOrDefault();
84-
if (tag == null) return null;
85-
return WithoutQuotes(tag);
69+
EntityTagHeaderValue etag = request.GetTypedHeaders().IfMatch?.FirstOrDefault();
70+
return etag?.Tag.Value?.Trim('"');
8671
}
8772

8873
internal static SummaryType RequestSummary(this HttpRequest request)
@@ -308,22 +293,8 @@ private static bool PreferRepresentation(this HttpRequestMessage request)
308293

309294
public static string IfMatchVersionId(this HttpRequestMessage request)
310295
{
311-
if (request.Headers.Count() > 0)
312-
{
313-
var tag = request.Headers.IfMatch.FirstOrDefault();
314-
if (tag != null)
315-
{
316-
return WithoutQuotes(tag.Tag);
317-
}
318-
else
319-
{
320-
return null;
321-
}
322-
}
323-
else
324-
{
325-
return null;
326-
}
296+
var etag = request.Headers.IfMatch.FirstOrDefault();
297+
return etag?.Tag?.Trim('"');
327298
}
328299

329300
private static SummaryType GetSummary(string summary)
@@ -404,4 +375,4 @@ internal static bool IsRawBinaryPostOrPutRequest(this HttpRequestMessage request
404375
&& !request.Content.IsContentTypeHeaderFhirMediaType()
405376
&& (request.Method == HttpMethod.Post || request.Method == HttpMethod.Put);
406377
}
407-
}
378+
}

src/Spark.Web/Controllers/FhirController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public async Task<FhirResponse> VRead(string type, string id, string vid)
5555
[HttpPut("{type}/{id?}")]
5656
public async Task<ActionResult<FhirResponse>> Update(string type, Resource resource, string id = null)
5757
{
58-
string versionId = Request.GetTypedHeaders().IfMatch?.FirstOrDefault()?.Tag.Buffer;
58+
string versionId = Request.IfMatchVersionId();
5959
Key key = Key.Create(type, id, versionId);
6060
if (key.HasResourceId())
6161
{

0 commit comments

Comments
 (0)