Fix some SonarCloud issues (#1058)

* Fix some SonarCloud issues

* added some xml comments
This commit is contained in:
Stef Heyenrath
2024-02-17 13:32:28 +01:00
committed by GitHub
parent 6ac95cf57d
commit 97a749d54a
12 changed files with 348 additions and 302 deletions

View File

@@ -2,22 +2,34 @@ using Stef.Validation;
using WireMock.Server;
// ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions
namespace WireMock.FluentAssertions;
/// <summary>
/// Provides assertion methods to verify the number of calls made to a WireMock server.
/// This class is used in the context of FluentAssertions.
/// </summary>
public class WireMockANumberOfCallsAssertions
{
public class WireMockANumberOfCallsAssertions
private readonly IWireMockServer _server;
private readonly int _callsCount;
/// <summary>
/// Initializes a new instance of the <see cref="WireMockANumberOfCallsAssertions"/> class.
/// </summary>
/// <param name="server">The WireMock server to assert against.</param>
/// <param name="callsCount">The expected number of calls to assert.</param>
public WireMockANumberOfCallsAssertions(IWireMockServer server, int callsCount)
{
private readonly IWireMockServer _server;
private readonly int _callsCount;
_server = Guard.NotNull(server);
_callsCount = callsCount;
}
public WireMockANumberOfCallsAssertions(IWireMockServer server, int callsCount)
{
_server = Guard.NotNull(server);
_callsCount = callsCount;
}
public WireMockAssertions Calls()
{
return new WireMockAssertions(_server, _callsCount);
}
/// <summary>
/// Returns an instance of <see cref="WireMockAssertions"/> which can be used to assert the expected number of calls.
/// </summary>
/// <returns>A <see cref="WireMockAssertions"/> instance for asserting the number of calls to the server.</returns>
public WireMockAssertions Calls()
{
return new WireMockAssertions(_server, _callsCount);
}
}

View File

@@ -2,50 +2,49 @@ using FluentAssertions.Primitives;
using WireMock.Server;
// ReSharper disable once CheckNamespace
namespace WireMock.FluentAssertions
namespace WireMock.FluentAssertions;
/// <summary>
/// Contains a number of methods to assert that the <see cref="IWireMockServer"/> is in the expected state.
/// </summary>
public class WireMockReceivedAssertions : ReferenceTypeAssertions<IWireMockServer, WireMockReceivedAssertions>
{
/// <summary>
/// Contains a number of methods to assert that the <see cref="IWireMockServer"/> is in the expected state.
/// Create a WireMockReceivedAssertions.
/// </summary>
public class WireMockReceivedAssertions : ReferenceTypeAssertions<IWireMockServer, WireMockReceivedAssertions>
/// <param name="server">The <see cref="IWireMockServer"/>.</param>
public WireMockReceivedAssertions(IWireMockServer server) : base(server)
{
/// <summary>
/// Create a WireMockReceivedAssertions.
/// </summary>
/// <param name="server">The <see cref="IWireMockServer"/>.</param>
public WireMockReceivedAssertions(IWireMockServer server) : base(server)
{
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received no calls.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedNoCalls()
{
return new WireMockAssertions(Subject, 0);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received a call.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedACall()
{
return new WireMockAssertions(Subject, null);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received n-calls.
/// </summary>
/// <param name="callsCount"></param>
/// <returns><see cref="WireMockANumberOfCallsAssertions"/></returns>
public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
{
return new WireMockANumberOfCallsAssertions(Subject, callsCount);
}
/// <inheritdoc />
protected override string Identifier => "wiremockserver";
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received no calls.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedNoCalls()
{
return new WireMockAssertions(Subject, 0);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received a call.
/// </summary>
/// <returns><see cref="WireMockAssertions"/></returns>
public WireMockAssertions HaveReceivedACall()
{
return new WireMockAssertions(Subject, null);
}
/// <summary>
/// Asserts if <see cref="IWireMockServer"/> has received n-calls.
/// </summary>
/// <param name="callsCount"></param>
/// <returns><see cref="WireMockANumberOfCallsAssertions"/></returns>
public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
{
return new WireMockANumberOfCallsAssertions(Subject, callsCount);
}
/// <inheritdoc />
protected override string Identifier => "wiremockserver";
}

View File

@@ -11,47 +11,47 @@ public interface IWireMockOpenApiParserExampleValues
/// <summary>
/// An example value for a Boolean.
/// </summary>
bool Boolean { get; set; }
bool Boolean { get; }
/// <summary>
/// An example value for an Integer.
/// </summary>
int Integer { get; set; }
int Integer { get; }
/// <summary>
/// An example value for a Float.
/// </summary>
float Float { get; set; }
float Float { get; }
/// <summary>
/// An example value for a Double.
/// </summary>
double Double { get; set; }
double Double { get; }
/// <summary>
/// An example value for a Date.
/// </summary>
Func<DateTime> Date { get; set; }
Func<DateTime> Date { get; }
/// <summary>
/// An example value for a DateTime.
/// </summary>
Func<DateTime> DateTime { get; set; }
Func<DateTime> DateTime { get; }
/// <summary>
/// An example value for Bytes.
/// </summary>
byte[] Bytes { get; set; }
byte[] Bytes { get; }
/// <summary>
/// An example value for a Object.
/// </summary>
object Object { get; set; }
object Object { get; }
/// <summary>
/// An example value for a String.
/// </summary>
string String { get; set; }
string String { get; }
/// <summary>
/// OpenApi Schema to generate dynamic examples more accurate

View File

@@ -11,31 +11,31 @@ namespace WireMock.Net.OpenApiParser.Settings;
public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserExampleValues
{
/// <inheritdoc />
public virtual bool Boolean { get => RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true; set { } }
public virtual bool Boolean => RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true;
/// <inheritdoc />
public virtual int Integer { get => RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42; set { } }
public virtual int Integer => RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42;
/// <inheritdoc />
public virtual float Float { get => RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f; set { } }
public virtual float Float => RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f;
/// <inheritdoc />
public virtual double Double { get => RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d; set { } }
public virtual double Double => RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d;
/// <inheritdoc />
public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } set { } }
public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } }
/// <inheritdoc />
public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } set { } }
public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } }
/// <inheritdoc />
public virtual byte[] Bytes { get => RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate(); set { } }
public virtual byte[] Bytes => RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate();
/// <inheritdoc />
public virtual object Object { get; set; } = "example-object";
public virtual object Object => "example-object";
/// <inheritdoc />
public virtual string String { get => RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string"; set { } }
public virtual string String => RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string";
/// <inheritdoc />
public virtual OpenApiSchema? Schema { get; set; }

View File

@@ -9,31 +9,31 @@ namespace WireMock.Net.OpenApiParser.Settings;
public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues
{
/// <inheritdoc />
public virtual bool Boolean { get; set; } = true;
public virtual bool Boolean => true;
/// <inheritdoc />
public virtual int Integer { get; set; } = 42;
public virtual int Integer => 42;
/// <inheritdoc />
public virtual float Float { get; set; } = 4.2f;
public virtual float Float => 4.2f;
/// <inheritdoc />
public virtual double Double { get; set; } = 4.2d;
public virtual double Double => 4.2d;
/// <inheritdoc />
public virtual Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date;
public virtual Func<DateTime> Date { get; } = () => System.DateTime.UtcNow.Date;
/// <inheritdoc />
public virtual Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow;
public virtual Func<DateTime> DateTime { get; } = () => System.DateTime.UtcNow;
/// <inheritdoc />
public virtual byte[] Bytes { get; set; } = { 48, 49, 50 };
public virtual byte[] Bytes { get; } = { 48, 49, 50 };
/// <inheritdoc />
public virtual object Object { get; set; } = "example-object";
public virtual object Object => "example-object";
/// <inheritdoc />
public virtual string String { get; set; } = "example-string";
public virtual string String => "example-string";
/// <inheritdoc />
public virtual OpenApiSchema? Schema { get; set; } = new();

View File

@@ -14,97 +14,97 @@ using WireMock.Owin.Mappers;
using WireMock.Services;
using WireMock.Util;
namespace WireMock.Owin
namespace WireMock.Owin;
internal partial class AspNetCoreSelfHost : IOwinSelfHost
{
internal partial class AspNetCoreSelfHost : IOwinSelfHost
private const string CorsPolicyName = "WireMock.Net - Policy";
private readonly CancellationTokenSource _cts = new();
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
private readonly IWireMockLogger _logger;
private readonly HostUrlOptions _urlOptions;
private Exception _runningException;
private IWebHost _host;
public bool IsStarted { get; private set; }
public List<string> Urls { get; } = new();
public List<int> Ports { get; } = new();
public Exception RunningException => _runningException;
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
{
private const string CorsPolicyName = "WireMock.Net - Policy";
Guard.NotNull(wireMockMiddlewareOptions);
Guard.NotNull(urlOptions);
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
private readonly IWireMockLogger _logger;
private readonly HostUrlOptions _urlOptions;
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
private Exception _runningException;
private IWebHost _host;
_wireMockMiddlewareOptions = wireMockMiddlewareOptions;
_urlOptions = urlOptions;
}
public bool IsStarted { get; private set; }
public Task StartAsync()
{
var builder = new WebHostBuilder();
public List<string> Urls { get; } = new();
public List<int> Ports { get; } = new();
public Exception RunningException => _runningException;
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
// Workaround for https://github.com/WireMock-Net/WireMock.Net/issues/292
// On some platforms, AppContext.BaseDirectory is null, which causes WebHostBuilder to fail if ContentRoot is not
// specified (even though we don't actually use that base path mechanism, since we have our own way of configuring
// a filesystem handler).
if (string.IsNullOrEmpty(AppContext.BaseDirectory))
{
Guard.NotNull(wireMockMiddlewareOptions);
Guard.NotNull(urlOptions);
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
_wireMockMiddlewareOptions = wireMockMiddlewareOptions;
_urlOptions = urlOptions;
builder.UseContentRoot(Directory.GetCurrentDirectory());
}
public Task StartAsync()
{
var builder = new WebHostBuilder();
// Workaround for https://github.com/WireMock-Net/WireMock.Net/issues/292
// On some platforms, AppContext.BaseDirectory is null, which causes WebHostBuilder to fail if ContentRoot is not
// specified (even though we don't actually use that base path mechanism, since we have our own way of configuring
// a filesystem handler).
if (string.IsNullOrEmpty(AppContext.BaseDirectory))
_host = builder
.UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
.ConfigureAppConfigurationUsingEnvironmentVariables()
.ConfigureServices(services =>
{
builder.UseContentRoot(Directory.GetCurrentDirectory());
}
_host = builder
.UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
.ConfigureAppConfigurationUsingEnvironmentVariables()
.ConfigureServices(services =>
{
services.AddSingleton(_wireMockMiddlewareOptions);
services.AddSingleton<IMappingMatcher, MappingMatcher>();
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
services.AddSingleton<IGuidUtils, GuidUtils>();
services.AddSingleton(_wireMockMiddlewareOptions);
services.AddSingleton<IMappingMatcher, MappingMatcher>();
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
services.AddSingleton<IGuidUtils, GuidUtils>();
#if NETCOREAPP3_1 || NET5_0_OR_GREATER
AddCors(services);
AddCors(services);
#endif
_wireMockMiddlewareOptions.AdditionalServiceRegistration?.Invoke(services);
})
.Configure(appBuilder =>
{
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
_wireMockMiddlewareOptions.AdditionalServiceRegistration?.Invoke(services);
})
.Configure(appBuilder =>
{
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
#if NETCOREAPP3_1 || NET5_0_OR_GREATER
UseCors(appBuilder);
UseCors(appBuilder);
#endif
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
appBuilder.UseMiddleware<WireMockMiddleware>();
appBuilder.UseMiddleware<WireMockMiddleware>();
_wireMockMiddlewareOptions.PostWireMockMiddlewareInit?.Invoke(appBuilder);
})
.UseKestrel(options =>
{
SetKestrelOptionsLimits(options);
_wireMockMiddlewareOptions.PostWireMockMiddlewareInit?.Invoke(appBuilder);
})
.UseKestrel(options =>
{
SetKestrelOptionsLimits(options);
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
})
.ConfigureKestrelServerOptions()
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
})
.ConfigureKestrelServerOptions()
#if NETSTANDARD1_3
.UseUrls(_urlOptions.GetDetails().Select(u => u.Url).ToArray())
.UseUrls(_urlOptions.GetDetails().Select(u => u.Url).ToArray())
#endif
.Build();
.Build();
return RunHost(_cts.Token);
}
return RunHost(_cts.Token);
}
private Task RunHost(CancellationToken token)
{
@@ -129,60 +129,59 @@ namespace WireMock.Owin
Ports.Add(port);
}
IsStarted = true;
});
IsStarted = true;
});
#if NETSTANDARD1_3
_logger.Info("Server using netstandard1.3");
_logger.Info("Server using netstandard1.3");
#elif NETSTANDARD2_0
_logger.Info("Server using netstandard2.0");
_logger.Info("Server using netstandard2.0");
#elif NETSTANDARD2_1
_logger.Info("Server using netstandard2.1");
_logger.Info("Server using netstandard2.1");
#elif NETCOREAPP3_1
_logger.Info("Server using .NET Core App 3.1");
_logger.Info("Server using .NET Core App 3.1");
#elif NET5_0
_logger.Info("Server using .NET 5.0");
_logger.Info("Server using .NET 5.0");
#elif NET6_0
_logger.Info("Server using .NET 6.0");
_logger.Info("Server using .NET 6.0");
#elif NET7_0
_logger.Info("Server using .NET 7.0");
_logger.Info("Server using .NET 7.0");
#elif NET8_0
_logger.Info("Server using .NET 8.0");
_logger.Info("Server using .NET 8.0");
#elif NET46
_logger.Info("Server using .NET Framework 4.6.1 or higher");
_logger.Info("Server using .NET Framework 4.6.1 or higher");
#endif
#if NETSTANDARD1_3
return Task.Run(() =>
{
_host.Run(token);
});
#else
return _host.RunAsync(token);
#endif
}
catch (Exception e)
return Task.Run(() =>
{
_runningException = e;
_logger.Error(e.ToString());
IsStarted = false;
return Task.CompletedTask;
}
_host.Run(token);
});
#else
return _host.RunAsync(token);
#endif
}
public Task StopAsync()
catch (Exception e)
{
_cts.Cancel();
_runningException = e;
_logger.Error(e.ToString());
IsStarted = false;
#if NETSTANDARD1_3
return Task.FromResult(true);
#else
return _host.StopAsync();
#endif
return Task.CompletedTask;
}
}
public Task StopAsync()
{
_cts.Cancel();
IsStarted = false;
#if NETSTANDARD1_3
return Task.CompletedTask;
#else
return _host.StopAsync();
#endif
}
}
#endif

View File

@@ -23,17 +23,17 @@ public partial class Request
}
/// <inheritdoc />
public IRequestBuilder WithClientIP(params string[] paths)
public IRequestBuilder WithClientIP(params string[] clientIPs)
{
return WithClientIP(MatchOperator.Or, paths);
return WithClientIP(MatchOperator.Or, clientIPs);
}
/// <inheritdoc />
public IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] paths)
public IRequestBuilder WithClientIP(MatchOperator matchOperator, params string[] clientIPs)
{
Guard.NotNullOrEmpty(paths);
Guard.NotNullOrEmpty(clientIPs);
_requestMatchers.Add(new RequestMessageClientIPMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, paths));
_requestMatchers.Add(new RequestMessageClientIPMatcher(MatchBehaviour.AcceptOnMatch, matchOperator, clientIPs));
return this;
}

View File

@@ -111,11 +111,11 @@ public partial class WireMockServer
Given(Request.Create().WithPath(AdminScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
// __admin/files/{filename}
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPut()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePut));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileGet));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingHead()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileHead));
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingPut()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePut));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileGet));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingHead()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileHead));
Given(Request.Create().WithPath(AdminFilesFilenamePathMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FileDelete));
// __admin/openapi
Given(Request.Create().WithPath($"{AdminOpenApi}/convert").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(OpenApiConvertToMappings));

View File

@@ -6,111 +6,120 @@ using WireMock.Matchers;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Server
namespace WireMock.Server;
public partial class WireMockServer
{
public partial class WireMockServer
private static readonly RegexMatcher AdminFilesFilenamePathMatcher = new(@"^\/__admin\/files\/.*$");
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
#region Files/{filename}
private IResponseMessage FilePost(IRequestMessage requestMessage)
{
private readonly RegexMatcher _adminFilesFilenamePathMatcher = new RegexMatcher(@"^\/__admin\/files\/.*$");
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
#region Files/{filename}
private IResponseMessage FilePost(IRequestMessage requestMessage)
if (requestMessage.BodyAsBytes is null)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
string mappingFolder = _settings.FileSystemHandler.GetMappingFolder();
if (!_settings.FileSystemHandler.FolderExists(mappingFolder))
{
_settings.FileSystemHandler.CreateFolder(mappingFolder);
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(200, "File created");
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
}
private IResponseMessage FilePut(IRequestMessage requestMessage)
var filename = GetFileNameFromRequestMessage(requestMessage);
var mappingFolder = _settings.FileSystemHandler.GetMappingFolder();
if (!_settings.FileSystemHandler.FolderExists(mappingFolder))
{
string filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
return ResponseMessageBuilder.Create(404, "File is not found");
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(200, "File updated");
_settings.FileSystemHandler.CreateFolder(mappingFolder);
}
private IResponseMessage FileGet(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(404, "File is not found");
}
byte[] bytes = _settings.FileSystemHandler.ReadFile(filename);
var response = new ResponseMessage
{
StatusCode = 200,
BodyData = new BodyData
{
BodyAsBytes = bytes,
DetectedBodyType = BodyType.Bytes,
DetectedBodyTypeFromContentType = BodyType.None
}
};
if (BytesEncodingUtils.TryGetEncoding(bytes, out var encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
{
response.BodyData.DetectedBodyType = BodyType.String;
response.BodyData.BodyAsString = encoding.GetString(bytes);
}
return response;
}
/// <summary>
/// Checks if file exists.
/// Note: Response is returned with no body as a head request doesn't accept a body, only the status code.
/// </summary>
/// <param name="requestMessage">The request message.</param>
private IResponseMessage FileHead(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound);
}
return ResponseMessageBuilder.Create(HttpStatusCode.NoContent);
}
private IResponseMessage FileDelete(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(404, "File is not deleted");
}
_settings.FileSystemHandler.DeleteFile(filename);
return ResponseMessageBuilder.Create(200, "File deleted.");
}
private string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
{
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
}
#endregion
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File created");
}
private IResponseMessage FilePut(IRequestMessage requestMessage)
{
if (requestMessage.BodyAsBytes is null)
{
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
}
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File updated");
}
private IResponseMessage FileGet(IRequestMessage requestMessage)
{
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
}
var bytes = _settings.FileSystemHandler.ReadFile(filename);
var response = new ResponseMessage
{
StatusCode = 200,
BodyData = new BodyData
{
BodyAsBytes = bytes,
DetectedBodyType = BodyType.Bytes,
DetectedBodyTypeFromContentType = BodyType.None
}
};
if (BytesEncodingUtils.TryGetEncoding(bytes, out var encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
{
response.BodyData.DetectedBodyType = BodyType.String;
response.BodyData.BodyAsString = encoding.GetString(bytes);
}
return response;
}
/// <summary>
/// Checks if file exists.
/// Note: Response is returned with no body as a head request doesn't accept a body, only the status code.
/// </summary>
/// <param name="requestMessage">The request message.</param>
private IResponseMessage FileHead(IRequestMessage requestMessage)
{
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound);
}
return ResponseMessageBuilder.Create(HttpStatusCode.NoContent);
}
private IResponseMessage FileDelete(IRequestMessage requestMessage)
{
var filename = GetFileNameFromRequestMessage(requestMessage);
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not deleted");
}
_settings.FileSystemHandler.DeleteFile(filename);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File deleted.");
}
private static string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
{
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
}
#endregion
}

View File

@@ -79,7 +79,7 @@ public partial class WireMockServer
private NotifyCollectionChangedEventHandler? _logEntriesChanged;
private void LogEntries_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void LogEntries_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (_logEntriesChanged is { })
{

View File

@@ -1,20 +1,48 @@
using System;
using Stef.Validation;
using WireMock.Matchers;
namespace WireMock.Settings;
public class ProxySaveMappingSetting<T>
/// <summary>
/// Represents settings for saving a proxy mapping with a non-nullable value and a specific match behaviour.
/// </summary>
/// <typeparam name="T">The non-nullable type of the value associated with the proxy save mapping setting.</typeparam>
public class ProxySaveMappingSetting<T> where T : notnull
{
public MatchBehaviour MatchBehaviour { get; } = MatchBehaviour.AcceptOnMatch;
/// <summary>
/// Gets the match behaviour for the proxy save mapping setting.
/// </summary>
/// <value>The match behaviour which determines how matches are evaluated.</value>
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// Gets the non-nullable value associated with the proxy save mapping setting.
/// </summary>
/// <value>The value of type <typeparamref name="T"/>.</value>
public T Value { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ProxySaveMappingSetting{T}"/> class with specified non-nullable value and match behaviour.
/// </summary>
/// <param name="value">The non-nullable value of type <typeparamref name="T"/>.</param>
/// <param name="matchBehaviour">The match behaviour (optional, default is <c>MatchBehaviour.AcceptOnMatch</c>.</param>
/// <exception cref="ArgumentNullException">Thrown if the <paramref name="value"/> is null.</exception>
public ProxySaveMappingSetting(T value, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
{
Value = value;
Value = Guard.NotNull(value);
MatchBehaviour = matchBehaviour;
}
/// <summary>
/// Converts a non-nullable value of type <typeparamref name="T"/> to a <see cref="ProxySaveMappingSetting{T}"/> implicitly.
/// </summary>
/// <param name="value">The non-nullable value to convert.</param>
public static implicit operator ProxySaveMappingSetting<T>(T value) => new(value);
public static implicit operator T(ProxySaveMappingSetting<T> @this) => @this.Value;
}
/// <summary>
/// Converts a <see cref="ProxySaveMappingSetting{T}"/> to its underlying non-nullable value of type <typeparamref name="T"/> implicitly.
/// </summary>
/// <param name="instance">The <see cref="ProxySaveMappingSetting{T}"/> to convert.</param>
public static implicit operator T(ProxySaveMappingSetting<T> instance) => instance.Value;
}

View File

@@ -121,8 +121,7 @@ internal static class CSharpFormatter
JTokenType.Boolean => jValue.Value != null ? string.Format(CultureInfo.InvariantCulture, "{0}", jValue.Value).ToLower() : Null,
JTokenType.Null => Null,
JTokenType.Undefined => Null,
JTokenType.Date when jValue.Value is DateTime dateValue =>
$"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})",
JTokenType.Date when jValue.Value is DateTime dateValue => $"DateTime.Parse({ToCSharpStringLiteral(dateValue.ToString("s"))})",
_ => $"UNHANDLED_CASE: {jValue.Type}"
},
_ => $"UNHANDLED_CASE: {token}"
@@ -140,12 +139,12 @@ internal static class CSharpFormatter
if (value.Contains('\n'))
{
var escapedValue = value?.Replace("\"", "\"\"") ?? string.Empty;
var escapedValue = value.Replace("\"", "\"\"");
return $"@\"{escapedValue}\"";
}
else
{
var escapedValue = value?.Replace("\"", "\\\"") ?? string.Empty;
var escapedValue = value.Replace("\"", "\\\"");
return $"\"{escapedValue}\"";
}
}