diff --git a/src/WireMock.Net.AspNetCore.Middleware/HttpDelegatingHandler/WireMockDelegationHandler.cs b/src/WireMock.Net.AspNetCore.Middleware/HttpDelegatingHandler/WireMockDelegationHandler.cs index 546cab2a..8b6a4c43 100644 --- a/src/WireMock.Net.AspNetCore.Middleware/HttpDelegatingHandler/WireMockDelegationHandler.cs +++ b/src/WireMock.Net.AspNetCore.Middleware/HttpDelegatingHandler/WireMockDelegationHandler.cs @@ -36,7 +36,6 @@ internal class WireMockDelegationHandler : DelegatingHandler protected override async Task 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); } } \ No newline at end of file diff --git a/test/WireMock.Net.Middleware.Tests/IntegrationTests.cs b/test/WireMock.Net.Middleware.Tests/IntegrationTests.cs index 00d420e0..8cac376e 100644 --- a/test/WireMock.Net.Middleware.Tests/IntegrationTests.cs +++ b/test/WireMock.Net.Middleware.Tests/IntegrationTests.cs @@ -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 diff --git a/test/WireMock.Net.TestWebApplication/Program.cs b/test/WireMock.Net.TestWebApplication/Program.cs index 63320a13..875e9292 100644 --- a/test/WireMock.Net.TestWebApplication/Program.cs +++ b/test/WireMock.Net.TestWebApplication/Program.cs @@ -13,6 +13,9 @@ public class Program var builder = WebApplication.CreateBuilder(args); + builder.Services.AddSingleton(); + builder.Services.AddHostedService(); + 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(); } } \ No newline at end of file diff --git a/test/WireMock.Net.TestWebApplication/TaskQueue.cs b/test/WireMock.Net.TestWebApplication/TaskQueue.cs new file mode 100644 index 00000000..7576621e --- /dev/null +++ b/test/WireMock.Net.TestWebApplication/TaskQueue.cs @@ -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 _taskChannel = Channel.CreateUnbounded(); + private readonly Channel<(Status, string)> _responseChannel = Channel.CreateUnbounded<(Status, string)>(); + + public async Task 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 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); +} \ No newline at end of file diff --git a/test/WireMock.Net.TestWebApplication/TestBackgroundService.cs b/test/WireMock.Net.TestWebApplication/TestBackgroundService.cs new file mode 100644 index 00000000..05923efc --- /dev/null +++ b/test/WireMock.Net.TestWebApplication/TestBackgroundService.cs @@ -0,0 +1,24 @@ +// Copyright © WireMock.Net + +namespace WireMock.Net.TestWebApplication; + +public class TestBackgroundService(HttpClient client, TaskQueue taskQueue, ILogger 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); + } + } + } +} \ No newline at end of file