Skip to content
Merged
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
20 changes: 19 additions & 1 deletion examples/WireMock.Net.Console.NET8/MainApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using SharpYaml.Model;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Models;
Expand Down Expand Up @@ -288,7 +289,24 @@ public static async Task RunAsync()

var todos = new Dictionary<int, Todo>();

var server = WireMockServer.Start();
var server = WireMockServer.Start(new WireMockServerSettings
{
Logger = new WireMockConsoleLogger(),

Port = 9091
});

server
.WhenRequest(r => r
.WithPath("/Content-Length")
.UsingAnyMethod()
)
.ThenRespondWith(r => r
.WithStatusCode(HttpStatusCode.OK)
.WithHeader("Content-Length", "42")
);

System.Console.ReadLine();

//server
// .Given(Request.Create()
Expand Down
38 changes: 38 additions & 0 deletions src/WireMock.Net.Minimal/Logging/WireMockAspNetCoreLogger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright © WireMock.Net

using Microsoft.Extensions.Logging;

namespace WireMock.Logging;

internal sealed class WireMockAspNetCoreLogger(IWireMockLogger logger, string categoryName) : ILogger
{
public IDisposable? BeginScope<TState>(TState state) where TState : notnull => null;

public bool IsEnabled(LogLevel logLevel) => logLevel >= LogLevel.Warning;

public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter)
{
if (!IsEnabled(logLevel))
{
return;
}

var message = formatter(state, exception);

if (exception != null)
{
message = $"{message} | Exception: {exception}";
}

switch (logLevel)
{
case LogLevel.Warning:
logger.Warn("[{0}] {1}", categoryName, message);
break;

default:
logger.Error("[{0}] {1}", categoryName, message);
break;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright © WireMock.Net

using Microsoft.Extensions.Logging;

namespace WireMock.Logging;

internal sealed class WireMockAspNetCoreLoggerProvider : ILoggerProvider
{
private readonly IWireMockLogger _logger;

public WireMockAspNetCoreLoggerProvider(IWireMockLogger logger)
{
_logger = logger;
}

public ILogger CreateLogger(string categoryName) => new WireMockAspNetCoreLogger(_logger, categoryName);

public void Dispose() { }
}
14 changes: 10 additions & 4 deletions src/WireMock.Net.Minimal/Owin/AspNetCoreSelfHost.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright © WireMock.Net

using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Stef.Validation;
using WireMock.Logging;
using WireMock.Owin.Mappers;
Expand Down Expand Up @@ -57,6 +57,12 @@ public Task StartAsync()
_host = builder
.UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
.ConfigureAppConfigurationUsingEnvironmentVariables()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddProvider(new WireMockAspNetCoreLoggerProvider(_logger));
logging.SetMinimumLevel(LogLevel.Warning);
})
.ConfigureServices(services =>
{
services.AddSingleton(_wireMockMiddlewareOptions);
Expand Down Expand Up @@ -169,10 +175,10 @@ private Task RunHost(CancellationToken token)

return _host.RunAsync(token);
}
catch (Exception e)
catch (Exception ex)
{
RunningException = e;
_logger.Error(e.ToString());
RunningException = ex;
_logger.Error("Error while RunAsync", ex);

IsStarted = false;

Expand Down
22 changes: 8 additions & 14 deletions src/WireMock.Net.Minimal/Owin/Mappers/OwinResponseMapper.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// Copyright © WireMock.Net

using System.Globalization;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Text;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
Expand Down Expand Up @@ -88,19 +86,15 @@ public async Task MapAsync(IResponseMessage? responseMessage, HttpResponse respo
break;
}

var statusCodeType = responseMessage.StatusCode?.GetType();
if (statusCodeType != null)
if (responseMessage.StatusCode is HttpStatusCode or int)
{
if (statusCodeType == typeof(int) || statusCodeType == typeof(int?) || statusCodeType.GetTypeInfo().IsEnum)
{
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
}
else if (statusCodeType == typeof(string))
{
// Note: this case will also match on null
int.TryParse(responseMessage.StatusCode as string, out var statusCodeTypeAsInt);
response.StatusCode = MapStatusCode(statusCodeTypeAsInt);
}
response.StatusCode = MapStatusCode((int) responseMessage.StatusCode);
}
else if (responseMessage.StatusCode is string statusCodeAsString)
{
// Note: this case will also match on null
_ = int.TryParse(statusCodeAsString, out var statusCodeTypeAsInt);
response.StatusCode = MapStatusCode(statusCodeTypeAsInt);
}

SetResponseHeaders(responseMessage, bytes != null, response);
Expand Down
2 changes: 0 additions & 2 deletions src/WireMock.Net.Minimal/Server/WireMockServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System.Collections.Concurrent;
using System.Linq;
using System.Net;
using System.Net.Http;
using AnyOfTypes;
using JetBrains.Annotations;
using JsonConverter.Newtonsoft.Json;
Expand Down
21 changes: 9 additions & 12 deletions test/WireMock.Net.Tests/Http/HttpRequestMessageHelperTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public void HttpRequestMessageHelper_Create()
var message = HttpRequestMessageHelper.Create(request, "http://url");

// Assert
message.Headers.GetValues("x").Should().Equal(new[] { "value-1" });
message.Headers.GetValues("x").Should().Equal(["value-1"]);
}

[Fact]
Expand Down Expand Up @@ -101,7 +101,7 @@ public async Task HttpRequestMessageHelper_Create_Json_With_ContentType_Applicat

// Assert
(await message.Content!.ReadAsStringAsync(_ct)).Should().Be("{\"x\":42}");
message.Content.Headers.GetValues("Content-Type").Should().Equal(new[] { "application/json" });
message.Content.Headers.GetValues("Content-Type").Should().Equal(["application/json"]);
}

[Fact]
Expand All @@ -121,7 +121,7 @@ public async Task HttpRequestMessageHelper_Create_Json_With_ContentType_Applicat

// Assert
(await message.Content!.ReadAsStringAsync(_ct)).Should().Be("{\"x\":42}");
message.Content.Headers.GetValues("Content-Type").Should().Equal(new[] { "application/json; charset=utf-8" });
message.Content.Headers.GetValues("Content-Type").Should().Equal(["application/json; charset=utf-8"]);
}

[Fact]
Expand All @@ -142,7 +142,7 @@ public async Task HttpRequestMessageHelper_Create_Json_With_ContentType_MultiPar

// Assert
(await message.Content!.ReadAsStringAsync(_ct)).Should().Be("{\"x\":42}");
message.Content.Headers.GetValues("Content-Type").Should().Equal(new[] { "multipart/form-data" });
message.Content.Headers.GetValues("Content-Type").Should().Equal(["multipart/form-data"]);
}


Expand All @@ -162,7 +162,7 @@ public void HttpRequestMessageHelper_Create_String_With_ContentType_ApplicationX
var message = HttpRequestMessageHelper.Create(request, "http://url");

// Assert
message.Content!.Headers.GetValues("Content-Type").Should().Equal(new[] { "application/xml" });
message.Content!.Headers.GetValues("Content-Type").Should().Equal(["application/xml"]);
}

[Fact]
Expand All @@ -181,7 +181,7 @@ public void HttpRequestMessageHelper_Create_String_With_ContentType_ApplicationX
var message = HttpRequestMessageHelper.Create(request, "http://url");

// Assert
message.Content!.Headers.GetValues("Content-Type").Should().Equal(new[] { "application/xml; charset=UTF-8" });
message.Content!.Headers.GetValues("Content-Type").Should().Equal(["application/xml; charset=UTF-8"]);
}

[Fact]
Expand All @@ -200,7 +200,7 @@ public void HttpRequestMessageHelper_Create_String_With_ContentType_ApplicationX
var message = HttpRequestMessageHelper.Create(request, "http://url");

// Assert
message.Content!.Headers.GetValues("Content-Type").Should().Equal(new[] { "application/xml; charset=Ascii" });
message.Content!.Headers.GetValues("Content-Type").Should().Equal(["application/xml; charset=Ascii"]);
}

[Fact]
Expand Down Expand Up @@ -242,7 +242,7 @@ Content of a txt

// Assert
(await message.Content!.ReadAsStringAsync(_ct)).Should().Be(body);
message.Content.Headers.GetValues("Content-Type").Should().Equal(new[] { "multipart/form-data" });
message.Content.Headers.GetValues("Content-Type").Should().Equal(["multipart/form-data"]);
}

[Theory]
Expand All @@ -269,7 +269,4 @@ public void HttpRequestMessageHelper_Create_ContentLengthAllowedForMethod(string
// Assert
message.Content?.Headers.ContentLength.Should().Be(resultShouldBe ? value : null);
}
}



}
12 changes: 10 additions & 2 deletions test/WireMock.Net.Tests/WebSockets/WebSocketIntegrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ public async Task WithTransformer_Should_Transform_Message_Using_Handlebars()
public async Task WithWebSocketProxy_Should_Proxy_Multiple_TextMessages()
{
// Arrange - Start target echo server
using var exampleEchoServer = WireMockServer.Start(new WireMockServerSettings
var exampleEchoServer = WireMockServer.Start(new WireMockServerSettings
{
Logger = new TestOutputHelperWireMockLogger(output),
Urls = ["ws://localhost:0"]
Expand All @@ -722,7 +722,7 @@ public async Task WithWebSocketProxy_Should_Proxy_Multiple_TextMessages()
);

// Arrange - Start proxy server
using var sut = WireMockServer.Start(new WireMockServerSettings
var sut = WireMockServer.Start(new WireMockServerSettings
{
Logger = new TestOutputHelperWireMockLogger(output),
Urls = ["ws://localhost:0"]
Expand Down Expand Up @@ -755,6 +755,14 @@ public async Task WithWebSocketProxy_Should_Proxy_Multiple_TextMessages()
}

await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test complete", _ct);

await Task.Delay(250, _ct);

sut.Stop();
sut.Dispose();

exampleEchoServer.Stop();
exampleEchoServer.Dispose();
}

[Fact]
Expand Down
48 changes: 46 additions & 2 deletions test/WireMock.Net.Tests/WireMockServerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,13 @@ public async Task WireMockServer_Should_AllowResponseHeaderContentLength_For_HEA
using var server = WireMockServer.Start();

server
.Given(Request.Create().WithPath(path).UsingHead())
.RespondWith(Response.Create().WithHeader(HttpKnownHeaderNames.ContentLength, length));
.WhenRequest(r => r
.WithPath(path)
.UsingHead()
)
.ThenRespondWith(r => r
.WithHeader(HttpKnownHeaderNames.ContentLength, length)
);

// Act
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Head, path);
Expand All @@ -442,6 +447,45 @@ public async Task WireMockServer_Should_AllowResponseHeaderContentLength_For_HEA
response.Content.Headers.GetValues(HttpKnownHeaderNames.ContentLength).Should().Contain(length);
}

#if NET8_0_OR_GREATER
[Theory]
[InlineData("DELETE")]
[InlineData("GET")]
[InlineData("OPTIONS")]
[InlineData("PATCH")]
[InlineData("POST")]
[InlineData("PUT")]
[InlineData("TRACE")]
public async Task WireMockServer_Should_LogAndThrowExceptionWhenInvalidContentLength(string method)
{
// Assign
const string length = "42";
var path = $"/InvalidContentLength_{Guid.NewGuid()}";
using var server = WireMockServer.Start(new WireMockServerSettings
{
Logger = new TestOutputHelperWireMockLogger(testOutputHelper)
});

server
.WhenRequest(r => r
.WithPath(path)
.UsingAnyMethod()
)
.ThenRespondWith(r => r
.WithStatusCode(HttpStatusCode.OK)
.WithHeader(HttpKnownHeaderNames.ContentLength, length)
);

// Act
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Parse(method), path);
var response = await server.CreateClient().SendAsync(httpRequestMessage, _ct);

// Assert
response.StatusCode.Should().Be(HttpStatusCode.InternalServerError);
testOutputHelper.Output.Should().Contain($"Response Content-Length mismatch: too few bytes written (0 of {length}).");
}
#endif

[Theory]
[InlineData("TRACE")]
[InlineData("GET")]
Expand Down
Loading