Skip to content

Commit d10dc51

Browse files
ishimmingsIan Shimmings
andauthored
Feature/cdms 445 fifo based on mrn (#37)
* Extracted Entry Reference (MRN) from SOAP document * Set SNS fifo message group id to mrn * Extracted correlation id from soap content to add to web headers and queue attributes * Optimised xml xpath searching; removed unused content type checks * Made soap xpath get property more resilient and added tests --------- Co-authored-by: Ian Shimmings <[email protected]>
1 parent 8168a08 commit d10dc51

19 files changed

+259
-243
lines changed

BtmsGateway.Test/EndToEnd/GeneralEndToEndTests.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ namespace BtmsGateway.Test.EndToEnd;
1111

1212
public sealed class GeneralEndToEndTests : IAsyncDisposable
1313
{
14-
private const string SoapContent = "<Envelope><Body><Message><xml>Content</xml></Message></Body></Envelope>";
1514
private const string RoutedPath = "/test/path";
1615

1716
private readonly string _headerCorrelationId = Guid.NewGuid().ToString("D");
17+
private readonly string _soapContent;
1818
private readonly DateTimeOffset _headerDate = DateTimeOffset.UtcNow.AddSeconds(-1).RoundDownToSecond();
1919
private readonly TestWebServer _testWebServer;
2020
private readonly HttpClient _httpClient;
@@ -24,7 +24,8 @@ public sealed class GeneralEndToEndTests : IAsyncDisposable
2424

2525
public GeneralEndToEndTests()
2626
{
27-
var routingConfig = new RoutingConfig()
27+
_soapContent = $"<Envelope><Body><Message><Xml>Content</Xml><CorrelationId>{_headerCorrelationId}</CorrelationId></Message></Body></Envelope>";
28+
var routingConfig = new RoutingConfig
2829
{
2930
NamedRoutes = new Dictionary<string, NamedRoute>
3031
{
@@ -54,15 +55,15 @@ public GeneralEndToEndTests()
5455

5556
_expectedRoutedUrl = $"http://testurlpath{RoutedPath}";
5657
_expectedForkedUrl = $"http://btmsurlpath/forked{RoutedPath}";
57-
_stringContent = new StringContent(SoapContent, Encoding.UTF8, MediaTypeNames.Application.Xml);
58+
_stringContent = new StringContent(_soapContent, Encoding.UTF8, MediaTypeNames.Application.Xml);
5859
}
5960

6061
public async ValueTask DisposeAsync() => await _testWebServer.DisposeAsync();
6162

6263
[Fact]
6364
public async Task When_routing_request_Then_should_respond_from_routed_request()
6465
{
65-
_testWebServer.RoutedHttpHandler.SetNextResponse(content: SoapContent);
66+
_testWebServer.RoutedHttpHandler.SetNextResponse(content: _soapContent);
6667

6768
var response = await _httpClient.PostAsync(RoutedPath, _stringContent);
6869

@@ -71,37 +72,37 @@ public async Task When_routing_request_Then_should_respond_from_routed_request()
7172
response.Headers.Date.Should().BeAfter(_headerDate);
7273
response.Headers.GetValues(MessageData.CorrelationIdHeaderName).FirstOrDefault().Should().Be(_headerCorrelationId);
7374
response.Headers.GetValues(MessageData.RequestedPathHeaderName).FirstOrDefault().Should().Be(RoutedPath);
74-
(await response.Content.ReadAsStringAsync()).Should().Be(SoapContent);
75+
(await response.Content.ReadAsStringAsync()).Should().Be(_soapContent);
7576
}
7677

7778
[Fact]
7879
public async Task When_routing_routed_request_Then_should_route_correctly()
7980
{
80-
_testWebServer.RoutedHttpHandler.SetNextResponse(content: SoapContent);
81+
_testWebServer.RoutedHttpHandler.SetNextResponse(content: _soapContent);
8182

8283
await _httpClient.PostAsync(RoutedPath, _stringContent);
8384

8485
var request = _testWebServer.RoutedHttpHandler.LastRequest;
8586
request?.RequestUri?.ToString().Should().Be(_expectedRoutedUrl);
8687
request?.Method.ToString().Should().Be("POST");
87-
(await request?.Content?.ReadAsStringAsync()!).Should().Be(SoapContent);
88+
(await request?.Content?.ReadAsStringAsync()!).Should().Be(_soapContent);
8889
request?.Content?.Headers.ContentType?.ToString().Should().StartWith(MediaTypeNames.Application.Xml);
8990
request?.Headers.Date?.Should().Be(_headerDate);
9091
request?.Headers.GetValues(MessageData.CorrelationIdHeaderName).FirstOrDefault().Should().Be(_headerCorrelationId);
9192

9293
var response = _testWebServer.RoutedHttpHandler.LastResponse;
9394
response?.StatusCode.Should().Be(HttpStatusCode.OK);
9495
response?.Content.Headers.ContentType?.ToString().Should().StartWith(MediaTypeNames.Application.Xml);
95-
(await response?.Content.ReadAsStringAsync()!).Should().Be(SoapContent);
96+
(await response?.Content.ReadAsStringAsync()!).Should().Be(_soapContent);
9697
}
9798

9899
[Fact]
99100
public async Task When_routing_forked_request_Then_should_route_correctly()
100101
{
101-
const string XmlForkedResponse = "<Envelope><Body><Message><xml>ForkedResponse</xml></Message></Body></Envelope>";
102-
var jsonContent = $"{{{Environment.NewLine} \"xml\": \"Content\"{Environment.NewLine}}}";
102+
var xmlForkedResponse = "<Envelope><Body><Message><Xml>ForkedResponse</Xml></Message></Body></Envelope>";
103+
var jsonContent = $"{{{Environment.NewLine} \"xml\": \"Content\",{Environment.NewLine} \"correlationId\": \"{_headerCorrelationId}\"{Environment.NewLine}}}";
103104

104-
_testWebServer.ForkedHttpHandler.SetNextResponse(content: XmlForkedResponse);
105+
_testWebServer.ForkedHttpHandler.SetNextResponse(content: xmlForkedResponse);
105106

106107
await _httpClient.PostAsync(RoutedPath, _stringContent);
107108

@@ -116,7 +117,7 @@ public async Task When_routing_forked_request_Then_should_route_correctly()
116117
var response = _testWebServer.ForkedHttpHandler.LastResponse;
117118
response?.StatusCode.Should().Be(HttpStatusCode.OK);
118119
response?.Content.Headers.ContentType?.ToString().Should().StartWith(MediaTypeNames.Application.Json);
119-
(await response?.Content.ReadAsStringAsync()!).Should().Be(XmlForkedResponse);
120+
(await response?.Content.ReadAsStringAsync()!).Should().Be(xmlForkedResponse);
120121
}
121122

122123
[Theory]

BtmsGateway.Test/Middleware/MessageDataTests.cs

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Net;
2+
using System.Text;
23
using BtmsGateway.Middleware;
34
using BtmsGateway.Services.Routing;
45
using BtmsGateway.Test.TestUtils;
@@ -11,6 +12,8 @@ namespace BtmsGateway.Test.Middleware;
1112

1213
public class MessageDataTests
1314
{
15+
private const string RequestBody = "<Envelope><Body><Root><Data>abc</Data><CorrelationId>correlation-id</CorrelationId></Root></Body></Envelope>";
16+
1417
private readonly DefaultHttpContext _httpContext = new()
1518
{
1619
Request =
@@ -19,10 +22,10 @@ public class MessageDataTests
1922
Scheme = "http",
2023
Method = "GET",
2124
Host = new HostString("localhost", 123),
25+
Body = new MemoryStream(Encoding.UTF8.GetBytes(RequestBody)),
2226
Headers =
2327
{
2428
new KeyValuePair<string, StringValues>("Content-Length", "999"),
25-
new KeyValuePair<string, StringValues>("X-Correlation-ID", "correlation-id"),
2629
new KeyValuePair<string, StringValues>("X-Custom", "custom")
2730
}
2831
}
@@ -76,25 +79,6 @@ public async Task When_receiving_a_get_request_that_should_not_be_processed_Then
7679
messageData.ShouldProcessRequest.Should().BeFalse();
7780
}
7881

79-
[Fact]
80-
public async Task When_receiving_a_routable_get_request_without_content_type_or_accept_headers_Then_it_should_break_up_the_request_parts()
81-
{
82-
_httpContext.Request.Path = new PathString("/cds/path");
83-
_httpContext.Request.Query = new QueryCollection(new Dictionary<string, StringValues> { { "a", "b" } });
84-
85-
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
86-
87-
messageData.HttpString.Should().Be("GET http://localhost:123/cds/path?a=b HTTP/1.1 ");
88-
messageData.Method.Should().Be("GET");
89-
messageData.Path.Should().Be("cds/path");
90-
messageData.Url.Should().Be("http://localhost:123/cds/path?a=b");
91-
messageData.CorrelationId.Should().Be("correlation-id");
92-
messageData.OriginalContentType.Should().Be("");
93-
messageData.OriginalContentAsString.Should().BeNull();
94-
messageData.ContentMap.ChedType.Should().BeNull();
95-
messageData.ContentMap.CountryCode.Should().BeNull();
96-
}
97-
9882
[Fact]
9983
public async Task When_receiving_a_routable_get_request_with_accept_header_Then_it_should_break_up_the_request_parts()
10084
{
@@ -110,7 +94,7 @@ public async Task When_creating_a_routable_get_request_without_host_header_Then_
11094
{
11195
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
11296

113-
var request = messageData.CreateForwardingRequestAsOriginal("https://localhost:456/cds/path", null);
97+
var request = messageData.CreateOriginalSoapRequest("https://localhost:456/cds/path", null);
11498

11599
request.RequestUri!.ToString().Should().Be("https://localhost:456/cds/path");
116100
request.Method.Should().Be(HttpMethod.Get);
@@ -126,7 +110,7 @@ public async Task When_creating_a_routable_get_request_with_host_header_Then_it_
126110
{
127111
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
128112

129-
var request = messageData.CreateForwardingRequestAsOriginal("https://localhost:456/cds/path", "host-header");
113+
var request = messageData.CreateOriginalSoapRequest("https://localhost:456/cds/path", "host-header");
130114

131115
request.Headers.Count().Should().Be(3);
132116
request.Headers.GetValues("host").Should().BeEquivalentTo("host-header");
@@ -136,10 +120,9 @@ public async Task When_creating_a_routable_get_request_with_host_header_Then_it_
136120
public async Task When_creating_a_routable_get_request_with_content_Then_it_should_create_forwarding_request()
137121
{
138122
_httpContext.Request.Headers.ContentType = "application/soap+xml";
139-
_httpContext.Request.Body = new MemoryStream("<root><data>abc</data></root>"u8.ToArray());
140123
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
141124

142-
var request = messageData.CreateForwardingRequestAsOriginal("https://localhost:456/cds/path", null);
125+
var request = messageData.CreateOriginalSoapRequest("https://localhost:456/cds/path", null);
143126

144127
request.Content.Should().BeNull();
145128
request.Headers.Count().Should().Be(3);
@@ -154,7 +137,7 @@ public async Task When_creating_a_routable_get_request_with_accept_header_Then_i
154137
_httpContext.Request.Headers.Add(new KeyValuePair<string, StringValues>("Accept", "application/json"));
155138
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
156139

157-
var request = messageData.CreateForwardingRequestAsOriginal("https://localhost:456/cds/path", null);
140+
var request = messageData.CreateOriginalSoapRequest("https://localhost:456/cds/path", null);
158141

159142
request.Headers.Count().Should().Be(3);
160143
request.Headers.GetValues(MessageData.CorrelationIdHeaderName).Should().BeEquivalentTo("correlation-id");
@@ -168,19 +151,17 @@ public async Task When_receiving_an_original_routable_post_request_Then_it_shoul
168151
_httpContext.Request.Method = "POST";
169152
_httpContext.Request.Path = new PathString("/cds/path");
170153
_httpContext.Request.Headers.ContentType = "application/soap+xml";
171-
_httpContext.Request.Body = new MemoryStream("<root><data>abc</data></root>"u8.ToArray());
172154

173155
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
174156

175157
messageData.HttpString.Should().Be("POST http://localhost:123/cds/path HTTP/1.1 application/soap+xml");
176158
messageData.Method.Should().Be("POST");
177159
messageData.Path.Should().Be("cds/path");
178160
messageData.Url.Should().Be("http://localhost:123/cds/path");
179-
messageData.CorrelationId.Should().Be("correlation-id");
180161
messageData.OriginalContentType.Should().Be("application/soap+xml");
181-
messageData.OriginalContentAsString.Should().Be("<root><data>abc</data></root>");
182-
messageData.ContentMap.ChedType.Should().Be("");
183-
messageData.ContentMap.CountryCode.Should().Be("");
162+
messageData.OriginalSoapContent.SoapString.Should().Be(RequestBody);
163+
messageData.ContentMap.EntryReference.Should().BeNull();
164+
messageData.ContentMap.CountryCode.Should().BeNull();
184165
}
185166

186167
[Fact]
@@ -189,13 +170,13 @@ public async Task When_receiving_an_original_routable_post_request_with_mappable
189170
_httpContext.Request.Method = "POST";
190171
_httpContext.Request.Path = new PathString("/cds/path");
191172
_httpContext.Request.Headers.ContentType = "application/soap+xml";
192-
_httpContext.Request.Body = new MemoryStream("<root><ched>CHEDPP</ched><DispatchCountryCode>NI</DispatchCountryCode></root>"u8.ToArray());
173+
_httpContext.Request.Body = new MemoryStream("<s:Envelope xmlns:s=\"http://soap\"><s:Body><ALVSClearanceRequest><Header><EntryReference>ALVSCDSTEST00000000688</EntryReference><DispatchCountryCode>NI</DispatchCountryCode><CorrelationId>123456789</CorrelationId></Header></ALVSClearanceRequest></s:Body></s:Envelope>"u8.ToArray());
193174

194175
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
195176

196-
messageData.OriginalContentAsString.Should().Be("<root><ched>CHEDPP</ched><DispatchCountryCode>NI</DispatchCountryCode></root>");
197-
messageData.ContentMap.ChedType.Should().Be("CHEDPP");
177+
messageData.ContentMap.EntryReference.Should().Be("ALVSCDSTEST00000000688");
198178
messageData.ContentMap.CountryCode.Should().Be("NI");
179+
messageData.ContentMap.CorrelationId.Should().Be("123456789");
199180
}
200181

201182
[Fact]
@@ -204,15 +185,14 @@ public async Task When_creating_a_routable_original_post_request_with_host_heade
204185
_httpContext.Request.Method = "POST";
205186
_httpContext.Request.Path = new PathString("/cds/path");
206187
_httpContext.Request.Headers.ContentType = "application/soap+xml";
207-
_httpContext.Request.Body = new MemoryStream("<root><data>abc</data></root>"u8.ToArray());
208188
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
209189

210-
var request = messageData.CreateForwardingRequestAsOriginal("https://localhost:456/cds/path", "host-header");
190+
var request = messageData.CreateOriginalSoapRequest("https://localhost:456/cds/path", "host-header");
211191

212192
request.RequestUri!.ToString().Should().Be("https://localhost:456/cds/path");
213193
request.Method.Should().Be(HttpMethod.Post);
214194
request.Version.Should().Be(Version.Parse("1.1"));
215-
(await request.Content!.ReadAsStringAsync()).Should().Be("<root><data>abc</data></root>");
195+
(await request.Content!.ReadAsStringAsync()).Should().Be(RequestBody);
216196
request.Content!.Headers.ContentType!.ToString().Should().Be("application/soap+xml; charset=utf-8");
217197
request.Headers.Count().Should().Be(4);
218198
request.Headers.GetValues(MessageData.CorrelationIdHeaderName).Should().BeEquivalentTo("correlation-id");
@@ -227,12 +207,11 @@ public async Task When_creating_a_routable_converted_post_request_Then_it_should
227207
_httpContext.Request.Method = "POST";
228208
_httpContext.Request.Path = new PathString("/cds/path");
229209
_httpContext.Request.Headers.ContentType = "application/soap+xml";
230-
_httpContext.Request.Body = new MemoryStream("<Envelope><Body><root><data>abc</data></root></Body></Envelope>"u8.ToArray());
231210
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
232211

233-
var request = messageData.CreateConvertedForwardingRequest("https://localhost:456/cds/path", null, "root");
212+
var request = messageData.CreateConvertedJsonRequest("https://localhost:456/cds/path", null, "Root");
234213

235-
(await request.Content!.ReadAsStringAsync()).LinuxLineEndings().Should().Be("{\n \"data\": \"abc\"\n}");
214+
(await request.Content!.ReadAsStringAsync()).LinuxLineEndings().Should().Be("{\n \"data\": \"abc\",\n \"correlationId\": \"correlation-id\"\n}");
236215
request.Content!.Headers.ContentType!.ToString().Should().Be("application/json; charset=utf-8");
237216
request.Headers.Count().Should().Be(3);
238217
request.Headers.GetValues("Accept").Should().BeEquivalentTo("application/json");
@@ -245,7 +224,6 @@ public async Task When_populating_a_response_with_content_and_existing_date_Then
245224
_httpContext.Request.Method = "POST";
246225
_httpContext.Request.Path = new PathString("/cds/path");
247226
_httpContext.Request.Headers.ContentType = "application/soap+xml";
248-
_httpContext.Request.Body = new MemoryStream("<Envelope><Body><root><data>abc</data></root></Body></Envelope>"u8.ToArray());
249227
var messageData = await MessageData.Create(_httpContext.Request, Logger.None);
250228
var responseBody = new MemoryStream();
251229
_httpContext.Response.Body = responseBody;

0 commit comments

Comments
 (0)