Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,18 @@ public OperationContext()
headers = new HttpCustomHeaderCollection();
}

/// <summary>
/// Creates an instance of OperationContext
/// </summary>
/// <param name="message">Initial http request message</param>
public OperationContext(HttpRequestMessage message)
{
_ = message ?? throw new ArgumentNullException(nameof(message));

Request = message;
properties = new Dictionary<string, string>();
headers = new HttpCustomHeaderCollection();
SetContentAsync(message).GetAwaiter().GetResult();
}

/// <summary>
/// Creates an instance of OperationContext
/// </summary>
/// <param name="message">Initial http request message</param>
/// <param name="headers">Initial header collection</param>
public OperationContext(HttpRequestMessage message, IHttpCustomHeaderCollection headers)
private OperationContext(HttpRequestMessage message, IHttpCustomHeaderCollection headers)
{
_ = message ?? throw new ArgumentNullException(nameof(message));

Request = message;
properties = new Dictionary<string, string>();
this.headers = headers;
SetContentAsync(message).GetAwaiter().GetResult();
}

/// <summary>
Expand Down Expand Up @@ -98,6 +83,16 @@ public string ContentString
/// </summary>
public Exception Error { get; set; }

public static async Task<OperationContext> CreateAsync(HttpRequestMessage message) =>
await CreateAsync(message, new HttpCustomHeaderCollection());

public static async Task<OperationContext> CreateAsync(HttpRequestMessage message, IHttpCustomHeaderCollection headers)
{
OperationContext context = new(message, headers);
await context.SetContentAsync(message);
return context;
}

/// <summary>
/// Updates the request URI and method.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public async Task<HttpResponseMessage> ExecuteAsync(HttpRequestMessage request)

try
{
_context = new(request, _headers);
_context = await OperationContext.CreateAsync(request, _headers);

_context = await ExecuteFiltersAsync(_inputFilters, _context);

Expand Down Expand Up @@ -222,7 +222,7 @@ private async Task ExecuteChannelsAsync(IChannelCollection channels, OperationCo

logger?.LogInformation("Pipeline {Name}-{Id} channel {ChannelName}-{ChannelId} is in state {State}.", Name, Id, channel.Name, channel.Id, channel.State);

var contentType = context.Request.Content?.Headers.ContentType.ToString();
var contentType = context.Request.Content?.Headers.ContentType?.ToString();
contentType ??= context.Request.Headers.Accept.ToString();

await channel.SendAsync(context.Content, new object[] { contentType });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<PackageId>Microsoft.AzureHealth.DataServices.Storage</PackageId>
<AssemblyName>Microsoft.AzureHealth.DataServices.Storage</AssemblyName>
<Description>Storage library to assist with creating custom operations for Azure Health Data Services.</Description>
<WarningsNotAsErrors>NU1903</WarningsNotAsErrors> <!-- To be able to restore Microsoft.Extensions.Caching.Memory -->
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AzureHealth.DataServices.Pipelines;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Expand All @@ -10,15 +11,15 @@ namespace Microsoft.AzureHealth.DataServices.Tests.Core
public class OperationContextTests
{
[TestMethod]
public void OperationContext_UpdateUri_Test()
public async Task OperationContext_UpdateUri_Test()
{
string content = "content";
string uriString = "https://example.org/fhir/Patient/1";
string expectedUriString = "https://example.org/fhir/Patient/2";
HttpMethod expectedMethod = HttpMethod.Post;

HttpRequestMessage request = new(HttpMethod.Get, new Uri(uriString));
OperationContext context = new(request);
OperationContext context = await OperationContext.CreateAsync(request);
context.UpdateFhirRequestUri(expectedMethod, "fhir", "Patient", "2");
context.ContentString = content;

Expand All @@ -28,14 +29,14 @@ public void OperationContext_UpdateUri_Test()
}

[TestMethod]
public void OperationContext_Properties_Test()
public async Task OperationContext_Properties_Test()
{
string propKey = "test";
string propValue = "value";
string uriString = "https://example.org/fhir/Patient/1";

HttpRequestMessage request = new(HttpMethod.Get, new Uri(uriString));
OperationContext context = new(request);
OperationContext context = await OperationContext.CreateAsync(request);
context.Properties.Add(propKey, propValue);
string actualValue = context.Properties[propKey];
Assert.AreEqual(propValue, actualValue, "Property mismatch.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.AzureHealth.DataServices.Channels;
using Microsoft.AzureHealth.DataServices.Filters;
using Microsoft.AzureHealth.DataServices.Headers;
using Microsoft.AzureHealth.DataServices.Pipelines;
using Microsoft.AzureHealth.DataServices.Tests.Assets;
using Microsoft.Extensions.Logging;
Expand Down Expand Up @@ -311,6 +312,38 @@ public async Task WebPipeline_WithContent_Test()
Assert.AreEqual(content, actualContent, "Content mismatch.");
}

[TestMethod]
public async Task WebPipeline_WithLongRunningContent_Test()
{
string content = "{ \"property\": \"value\" }";
HttpMethod method = HttpMethod.Get;
string requestUriString = "http://example.org/test";
HttpRequestMessage request = new(method, requestUriString);
request.Content = new DelayedHttpContent(content);

IInputFilterCollection filters = new InputFilterCollection();
IInputChannelCollection channels = new InputChannelCollection();
filters.Add(new FakeFilter());

// filters.Add(new FakeFilterWithContent());
channels.Add(new FakeChannel());

IPipeline<HttpRequestMessage, HttpResponseMessage> pipeline = new WebPipeline(filters, channels);

bool complete = false;
pipeline.OnComplete += (a, args) =>
{
complete = true;
};

HttpResponseMessage response = await pipeline.ExecuteAsync(request);
Assert.IsNotNull(response, "Response is null.");
Assert.IsTrue(complete, "Pipeline not complete.");
string actualContent = await response.Content.ReadAsStringAsync();
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode, "Http status code mismatch.");
Assert.AreEqual(content, actualContent, "Content mismatch.");
}

[TestMethod]
public async Task WebPipeline_ForcedError_Test()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

namespace Microsoft.AzureHealth.DataServices.Headers;

/// <summary>
/// Purpose of this mock httpContext to mimic situation when creation of httprequest content takes a lot of time.
/// </summary>
/// <param name="content">content</param>
/// <param name="miliseconds">how long to delay before creating content</param>
public class DelayedHttpContent(string content, int miliseconds = 1000) : HttpContent
{
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
await Task.Delay(miliseconds);
stream.Write(Encoding.UTF8.GetBytes(content));
}

protected override bool TryComputeLength(out long length)
{
length = content.Length;
return true;
}
}