Enable support for WireMock Middleware in Hosted Services (#1285)

This commit is contained in:
Emil Tang Kristensen
2025-04-25 16:35:55 +02:00
committed by GitHub
parent 0fd190b5a3
commit 9392069f8a
5 changed files with 94 additions and 3 deletions

View File

@@ -36,7 +36,6 @@ internal class WireMockDelegationHandler : DelegatingHandler
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
Guard.NotNull(request);
Guard.NotNull(_httpContextAccessor.HttpContext);
if (_settings.AlwaysRedirect || IsWireMockRedirectHeaderSetToTrue())
{
@@ -57,16 +56,30 @@ internal class WireMockDelegationHandler : DelegatingHandler
private bool IsWireMockRedirectHeaderSetToTrue()
{
var httpContext = _httpContextAccessor.HttpContext;
if (httpContext is null)
{
_logger.LogDebug("HttpContext is not available in current runtime environment");
return false;
}
return
_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue(AppConstants.HEADER_REDIRECT, out var values) &&
httpContext.Request.Headers.TryGetValue(AppConstants.HEADER_REDIRECT, out var values) &&
bool.TryParse(values.ToString(), out var shouldRedirectToWireMock) && shouldRedirectToWireMock;
}
private bool TryGetDelayHeaderValue(out int delayInMs)
{
delayInMs = 0;
var httpContext = _httpContextAccessor.HttpContext;
if (httpContext is null)
{
_logger.LogDebug("HttpContext is not available in current runtime environment");
return false;
}
return
_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue(AppConstants.HEADER_RESPONSE_DELAY, out var values) &&
httpContext.Request.Headers.TryGetValue(AppConstants.HEADER_RESPONSE_DELAY, out var values) &&
int.TryParse(values.ToString(), out delayInMs);
}
}

View File

@@ -10,6 +10,7 @@ public class IntegrationTests
[Theory]
[InlineData("/real1", "Hello 1 from WireMock.Net !")]
[InlineData("/real2", "Hello 2 from WireMock.Net !")]
[InlineData("/real3", "Hello 3 from WireMock.Net !")]
public async Task CallingRealApi_WithAlwaysRedirectToWireMockIsTrue(string requestUri, string expectedResponse)
{
// Arrange

View File

@@ -13,6 +13,9 @@ public class Program
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<TaskQueue>();
builder.Services.AddHostedService<TestBackgroundService>();
builder.Services.AddWireMockService(server =>
{
server.Given(Request.Create()
@@ -28,6 +31,13 @@ public class Program
).RespondWith(Response.Create()
.WithBody("Hello 2 from WireMock.Net !")
);
server.Given(Request.Create()
.WithPath("/test3")
.UsingAnyMethod()
).RespondWith(Response.Create()
.WithBody("Hello 3 from WireMock.Net !")
);
}, alwaysRedirectToWireMock);
var app = builder.Build();
@@ -44,6 +54,11 @@ public class Program
return await client.GetStringAsync("https://real-api:12345/test2");
});
app.MapGet("/real3", async (TaskQueue taskQueue, CancellationToken cancellationToken) =>
{
return await taskQueue.Enqueue("https://real-api:12345/test3", cancellationToken);
});
await app.RunAsync();
}
}

View File

@@ -0,0 +1,38 @@
// Copyright © WireMock.Net
using System.Threading.Channels;
namespace WireMock.Net.TestWebApplication;
public class TaskQueue
{
private enum Status
{
Success,
Error
}
private readonly Channel<string> _taskChannel = Channel.CreateUnbounded<string>();
private readonly Channel<(Status, string)> _responseChannel = Channel.CreateUnbounded<(Status, string)>();
public async Task<string> Enqueue(string taskId, CancellationToken cancellationToken)
{
await _taskChannel.Writer.WriteAsync(taskId, cancellationToken);
var (status, result) = await _responseChannel.Reader.ReadAsync(cancellationToken);
if (status == Status.Error)
{
throw new InvalidOperationException($"Received an error response from the task processor: ${result}");
}
return result;
}
public IAsyncEnumerable<string> ReadTasks(CancellationToken stoppingToken) =>
_taskChannel.Reader.ReadAllAsync(stoppingToken);
public async Task WriteResponse(string result, CancellationToken stoppingToken) =>
await _responseChannel.Writer.WriteAsync((Status.Success, result), stoppingToken);
public async Task WriteErrorResponse(string result, CancellationToken stoppingToken) =>
await _responseChannel.Writer.WriteAsync((Status.Error, result), stoppingToken);
}

View File

@@ -0,0 +1,24 @@
// Copyright © WireMock.Net
namespace WireMock.Net.TestWebApplication;
public class TestBackgroundService(HttpClient client, TaskQueue taskQueue, ILogger<TestBackgroundService> logger)
: BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await foreach (var item in taskQueue.ReadTasks(stoppingToken))
{
try
{
var result = await client.GetStringAsync(item, stoppingToken);
await taskQueue.WriteResponse(result, stoppingToken);
}
catch (ArgumentNullException argNullEx)
{
logger.LogError(argNullEx, "Null exception");
await taskQueue.WriteErrorResponse(argNullEx.Message, stoppingToken);
}
}
}
}