mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-19 00:27:04 +01:00
Add setting to skip saving the string-response in the logging when using WithBody(Func...) (#828)
* Add extra unit-test for Response WithBody (dynamic code) * DoNotSaveDynamicResponseInLogEntry * update SettingsModel * fix * .
This commit is contained in:
@@ -1,82 +1,92 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Admin.Settings
|
||||
namespace WireMock.Admin.Settings;
|
||||
|
||||
/// <summary>
|
||||
/// Settings
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class SettingsModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings
|
||||
/// Gets or sets the global delay in milliseconds.
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class SettingsModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the global delay in milliseconds.
|
||||
/// </summary>
|
||||
public int? GlobalProcessingDelay { get; set; }
|
||||
public int? GlobalProcessingDelay { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if partial mapping is allowed.
|
||||
/// </summary>
|
||||
public bool? AllowPartialMapping { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets if partial mapping is allowed.
|
||||
/// </summary>
|
||||
public bool? AllowPartialMapping { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the RequestLog expiration in hours
|
||||
/// </summary>
|
||||
public int? RequestLogExpirationDuration { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the RequestLog expiration in hours
|
||||
/// </summary>
|
||||
public int? RequestLogExpirationDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the MaxRequestLog count.
|
||||
/// </summary>
|
||||
public int? MaxRequestLogCount { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the MaxRequestLog count.
|
||||
/// </summary>
|
||||
public int? MaxRequestLogCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
||||
/// </summary>
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
/// <summary>
|
||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
||||
/// </summary>
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handle all requests synchronously. (default set to false).
|
||||
/// </summary>
|
||||
public bool? HandleRequestsSynchronously { get; set; }
|
||||
/// <summary>
|
||||
/// Handle all requests synchronously. (default set to false).
|
||||
/// </summary>
|
||||
public bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Throw an exception when the Matcher fails because of invalid input. (default set to false).
|
||||
/// </summary>
|
||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||
/// <summary>
|
||||
/// Throw an exception when the Matcher fails because of invalid input. (default set to false).
|
||||
/// </summary>
|
||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Use the RegexExtended instead of the default <see cref="Regex"/>. (default set to true).
|
||||
/// </summary>
|
||||
public bool? UseRegexExtended { get; set; }
|
||||
/// <summary>
|
||||
/// Use the RegexExtended instead of the default <see cref="Regex"/>. (default set to true).
|
||||
/// </summary>
|
||||
public bool? UseRegexExtended { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/>. (default set to false).
|
||||
/// </summary>
|
||||
public bool? SaveUnmatchedRequests { get; set; }
|
||||
/// <summary>
|
||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/>. (default set to false).
|
||||
/// </summary>
|
||||
public bool? SaveUnmatchedRequests { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the static mappings should be read at startup.
|
||||
/// </summary>
|
||||
public bool? ReadStaticMappings { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets if the static mappings should be read at startup.
|
||||
/// </summary>
|
||||
public bool? ReadStaticMappings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Watch the static mapping files + folder for changes when running.
|
||||
/// </summary>
|
||||
public bool? WatchStaticMappings { get; set; }
|
||||
/// <summary>
|
||||
/// Watch the static mapping files + folder for changes when running.
|
||||
/// </summary>
|
||||
public bool? WatchStaticMappings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A value indicating whether subdirectories within the static mappings path should be monitored.
|
||||
/// </summary>
|
||||
public bool? WatchStaticMappingsInSubdirectories { get; set; }
|
||||
/// <summary>
|
||||
/// A value indicating whether subdirectories within the static mappings path should be monitored.
|
||||
/// </summary>
|
||||
public bool? WatchStaticMappingsInSubdirectories { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
|
||||
/// </summary>
|
||||
public string? CorsPolicyOptions { get; set; }
|
||||
/// <summary>
|
||||
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
|
||||
/// </summary>
|
||||
public string? CorsPolicyOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The proxy and record settings.
|
||||
/// </summary>
|
||||
public ProxyAndRecordSettingsModel? ProxyAndRecordSettings { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// The proxy and record settings.
|
||||
/// </summary>
|
||||
public ProxyAndRecordSettingsModel? ProxyAndRecordSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines on which scheme (http/https) to host. (This overrides the <c>UseSSL</c> value).
|
||||
/// </summary>
|
||||
public HostingScheme? HostingScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||
/// </summary>
|
||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Util;
|
||||
@@ -59,4 +57,9 @@ public interface IBodyData
|
||||
/// The body encoding.
|
||||
/// </summary>
|
||||
Encoding? Encoding { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if this BodyData is the result of a dynamically created response-string. (
|
||||
/// </summary>
|
||||
public string? IsFuncUsed { get; set; }
|
||||
}
|
||||
@@ -12,13 +12,13 @@ public class LogEntry : ILogEntry
|
||||
public Guid Guid { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.RequestMessage" />
|
||||
public IRequestMessage RequestMessage { get; set; }
|
||||
public IRequestMessage RequestMessage { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
|
||||
public IResponseMessage ResponseMessage { get; set; }
|
||||
public IResponseMessage ResponseMessage { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
|
||||
public IRequestMatchResult RequestMatchResult { get; set; }
|
||||
public IRequestMatchResult RequestMatchResult { get; set; } = null!;
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.MappingGuid" />
|
||||
public Guid? MappingGuid { get; set; }
|
||||
@@ -33,5 +33,5 @@ public class LogEntry : ILogEntry
|
||||
public string? PartialMappingTitle { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
|
||||
public IRequestMatchResult PartialMatchResult { get; set; }
|
||||
public IRequestMatchResult PartialMatchResult { get; set; } = null!;
|
||||
}
|
||||
@@ -21,6 +21,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.ThrowException"/>
|
||||
public bool ThrowException { get; }
|
||||
|
||||
|
||||
@@ -1,41 +1,43 @@
|
||||
using System.Text;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Util
|
||||
namespace WireMock.Util;
|
||||
|
||||
/// <summary>
|
||||
/// BodyData
|
||||
/// </summary>
|
||||
public class BodyData : IBodyData
|
||||
{
|
||||
/// <summary>
|
||||
/// BodyData
|
||||
/// </summary>
|
||||
public class BodyData : IBodyData
|
||||
{
|
||||
/// <inheritdoc cref="IBodyData.Encoding" />
|
||||
public Encoding? Encoding { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.Encoding" />
|
||||
public Encoding? Encoding { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? BodyAsString { get; set; }
|
||||
/// <inheritdoc />
|
||||
public string? BodyAsString { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.BodyAsJson" />
|
||||
public object? BodyAsJson { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.BodyAsJson" />
|
||||
public object? BodyAsJson { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.BodyAsBytes" />
|
||||
public byte[]? BodyAsBytes { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.BodyAsBytes" />
|
||||
public byte[]? BodyAsBytes { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.BodyAsJsonIndented" />
|
||||
public bool? BodyAsJsonIndented { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.BodyAsJsonIndented" />
|
||||
public bool? BodyAsJsonIndented { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.BodyAsFile" />
|
||||
public string? BodyAsFile { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.BodyAsFile" />
|
||||
public string? BodyAsFile { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.BodyAsFileIsCached" />
|
||||
public bool? BodyAsFileIsCached { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.BodyAsFileIsCached" />
|
||||
public bool? BodyAsFileIsCached { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.DetectedBodyType" />
|
||||
public BodyType? DetectedBodyType { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.DetectedBodyType" />
|
||||
public BodyType? DetectedBodyType { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IBodyData.DetectedBodyTypeFromContentType" />
|
||||
public BodyType? DetectedBodyTypeFromContentType { get; set; }
|
||||
/// <inheritdoc cref="IBodyData.DetectedBodyTypeFromContentType" />
|
||||
public BodyType? DetectedBodyTypeFromContentType { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IRequestMessage.DetectedCompression" />
|
||||
public string? DetectedCompression { get; set; }
|
||||
}
|
||||
/// <inheritdoc cref="IRequestMessage.DetectedCompression" />
|
||||
public string? DetectedCompression { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? IsFuncUsed { get; set; }
|
||||
}
|
||||
@@ -69,4 +69,6 @@ internal interface IWireMockMiddlewareOptions
|
||||
bool CustomCertificateDefined { get; }
|
||||
|
||||
bool? SaveUnmatchedRequests { get; set; }
|
||||
|
||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||
}
|
||||
@@ -32,22 +32,25 @@ namespace WireMock.Owin
|
||||
private readonly IOwinRequestMapper _requestMapper;
|
||||
private readonly IOwinResponseMapper _responseMapper;
|
||||
private readonly IMappingMatcher _mappingMatcher;
|
||||
private readonly LogEntryMapper _logEntryMapper;
|
||||
|
||||
#if !USE_ASPNETCORE
|
||||
public WireMockMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinRequestMapper requestMapper, IOwinResponseMapper responseMapper, IMappingMatcher mappingMatcher) : base(next)
|
||||
{
|
||||
_options = Guard.NotNull(options, nameof(options));
|
||||
_requestMapper = Guard.NotNull(requestMapper, nameof(requestMapper));
|
||||
_responseMapper = Guard.NotNull(responseMapper, nameof(responseMapper));
|
||||
_mappingMatcher = Guard.NotNull(mappingMatcher, nameof(mappingMatcher));
|
||||
_options = Guard.NotNull(options);
|
||||
_requestMapper = Guard.NotNull(requestMapper);
|
||||
_responseMapper = Guard.NotNull(responseMapper);
|
||||
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
||||
_logEntryMapper = new LogEntryMapper(options);
|
||||
}
|
||||
#else
|
||||
public WireMockMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinRequestMapper requestMapper, IOwinResponseMapper responseMapper, IMappingMatcher mappingMatcher)
|
||||
{
|
||||
_options = Guard.NotNull(options, nameof(options));
|
||||
_requestMapper = Guard.NotNull(requestMapper, nameof(requestMapper));
|
||||
_responseMapper = Guard.NotNull(responseMapper, nameof(responseMapper));
|
||||
_mappingMatcher = Guard.NotNull(mappingMatcher, nameof(mappingMatcher));
|
||||
_options = Guard.NotNull(options);
|
||||
_requestMapper = Guard.NotNull(requestMapper);
|
||||
_responseMapper = Guard.NotNull(responseMapper);
|
||||
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
||||
_logEntryMapper = new LogEntryMapper(options);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -264,7 +267,7 @@ namespace WireMock.Owin
|
||||
|
||||
private void LogRequest(LogEntry entry, bool addRequest)
|
||||
{
|
||||
_options.Logger.DebugRequestResponse(LogEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||
|
||||
if (addRequest)
|
||||
{
|
||||
|
||||
@@ -84,4 +84,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.SaveUnmatchedRequests"/>
|
||||
public bool? SaveUnmatchedRequests { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||
}
|
||||
@@ -21,7 +21,8 @@ public partial class Response
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = bodyFactory(req),
|
||||
Encoding = encoding ?? Encoding.UTF8
|
||||
Encoding = encoding ?? Encoding.UTF8,
|
||||
IsFuncUsed = "Func<IRequestMessage, string>"
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -37,7 +38,8 @@ public partial class Response
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = await bodyFactory(req).ConfigureAwait(false),
|
||||
Encoding = encoding ?? Encoding.UTF8
|
||||
Encoding = encoding ?? Encoding.UTF8,
|
||||
IsFuncUsed = "Func<IRequestMessage, Task<string>>"
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -325,15 +325,15 @@ public partial class Response : IResponseBuilder
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
||||
throw new NotSupportedException($"TransformerType '{TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
return (responseMessageTransformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
}
|
||||
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true && responseMessage.BodyData?.BodyAsFile is not null)
|
||||
{
|
||||
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData!.BodyAsFile);
|
||||
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
||||
}
|
||||
|
||||
return (responseMessage, null);
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
using System.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Owin;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Serialization;
|
||||
|
||||
internal static class LogEntryMapper
|
||||
internal class LogEntryMapper
|
||||
{
|
||||
public static LogEntryModel Map(ILogEntry logEntry)
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
|
||||
public LogEntryMapper(IWireMockMiddlewareOptions options)
|
||||
{
|
||||
_options = Guard.NotNull(options);
|
||||
}
|
||||
|
||||
public LogEntryModel Map(ILogEntry logEntry)
|
||||
{
|
||||
var logRequestModel = new LogRequestModel
|
||||
{
|
||||
@@ -78,25 +87,7 @@ internal static class LogEntryMapper
|
||||
logResponseModel.DetectedBodyType = logEntry.ResponseMessage.BodyData.DetectedBodyType;
|
||||
logResponseModel.DetectedBodyTypeFromContentType = logEntry.ResponseMessage.BodyData.DetectedBodyTypeFromContentType;
|
||||
|
||||
switch (logEntry.ResponseMessage.BodyData.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
logResponseModel.Body = logEntry.ResponseMessage.BodyData.BodyAsString;
|
||||
break;
|
||||
|
||||
case BodyType.Json:
|
||||
logResponseModel.BodyAsJson = logEntry.ResponseMessage.BodyData.BodyAsJson;
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
logResponseModel.BodyAsBytes = logEntry.ResponseMessage.BodyData.BodyAsBytes;
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
||||
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||
break;
|
||||
}
|
||||
MapBody(logEntry, logResponseModel);
|
||||
|
||||
logResponseModel.BodyEncoding = logEntry.ResponseMessage.BodyData.Encoding != null
|
||||
? new EncodingModel
|
||||
@@ -124,6 +115,36 @@ internal static class LogEntryMapper
|
||||
};
|
||||
}
|
||||
|
||||
private void MapBody(ILogEntry logEntry, LogResponseModel logResponseModel)
|
||||
{
|
||||
switch (logEntry.ResponseMessage.BodyData!.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
if (!string.IsNullOrEmpty(logEntry.ResponseMessage.BodyData.IsFuncUsed) && _options.DoNotSaveDynamicResponseInLogEntry == true)
|
||||
{
|
||||
logResponseModel.Body = logEntry.ResponseMessage.BodyData.IsFuncUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
logResponseModel.Body = logEntry.ResponseMessage.BodyData.BodyAsString;
|
||||
}
|
||||
break;
|
||||
|
||||
case BodyType.Json:
|
||||
logResponseModel.BodyAsJson = logEntry.ResponseMessage.BodyData.BodyAsJson;
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
logResponseModel.BodyAsBytes = logEntry.ResponseMessage.BodyData.BodyAsBytes;
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
||||
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static LogRequestMatchModel? Map(IRequestMatchResult? matchResult)
|
||||
{
|
||||
if (matchResult == null)
|
||||
|
||||
@@ -277,6 +277,8 @@ public partial class WireMockServer
|
||||
UseRegexExtended = _settings.UseRegexExtended,
|
||||
WatchStaticMappings = _settings.WatchStaticMappings,
|
||||
WatchStaticMappingsInSubdirectories = _settings.WatchStaticMappingsInSubdirectories,
|
||||
HostingScheme = _settings.HostingScheme,
|
||||
DoNotSaveDynamicResponseInLogEntry = _settings.DoNotSaveDynamicResponseInLogEntry,
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
CorsPolicyOptions = _settings.CorsPolicyOptions?.ToString()
|
||||
@@ -305,6 +307,7 @@ public partial class WireMockServer
|
||||
_settings.UseRegexExtended = settings.UseRegexExtended;
|
||||
_settings.WatchStaticMappings = settings.WatchStaticMappings;
|
||||
_settings.WatchStaticMappingsInSubdirectories = settings.WatchStaticMappingsInSubdirectories;
|
||||
_settings.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||
|
||||
InitSettings(_settings);
|
||||
|
||||
@@ -525,7 +528,7 @@ public partial class WireMockServer
|
||||
return ResponseMessageBuilder.Create("Request not found", 404);
|
||||
}
|
||||
|
||||
var model = LogEntryMapper.Map(entry);
|
||||
var model = new LogEntryMapper(_options).Map(entry);
|
||||
|
||||
return ToJson(model);
|
||||
}
|
||||
@@ -546,9 +549,10 @@ public partial class WireMockServer
|
||||
#region Requests
|
||||
private IResponseMessage RequestsGet(IRequestMessage requestMessage)
|
||||
{
|
||||
var logEntryMapper = new LogEntryMapper(_options);
|
||||
var result = LogEntries
|
||||
.Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
|
||||
.Select(LogEntryMapper.Map);
|
||||
.Select(logEntryMapper.Map);
|
||||
|
||||
return ToJson(result);
|
||||
}
|
||||
@@ -578,7 +582,8 @@ public partial class WireMockServer
|
||||
}
|
||||
}
|
||||
|
||||
var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(LogEntryMapper.Map);
|
||||
var logEntryMapper = new LogEntryMapper(_options);
|
||||
var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(logEntryMapper.Map);
|
||||
|
||||
return ToJson(result);
|
||||
}
|
||||
|
||||
@@ -295,6 +295,7 @@ public partial class WireMockServer : IWireMockServer
|
||||
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
|
||||
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
_options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||
_options.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||
|
||||
if (settings.CustomCertificateDefined)
|
||||
{
|
||||
|
||||
@@ -252,6 +252,12 @@ namespace WireMock.Settings
|
||||
[PublicAPI]
|
||||
public bool? SaveUnmatchedRequests { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Custom matcher mappings for static mappings
|
||||
/// </summary>
|
||||
|
||||
@@ -54,7 +54,8 @@ public static class WireMockServerSettingsParser
|
||||
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
|
||||
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
|
||||
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
|
||||
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme))
|
||||
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme)),
|
||||
DoNotSaveDynamicResponseInLogEntry = parser.GetBoolValue(nameof(WireMockServerSettings.DoNotSaveDynamicResponseInLogEntry))
|
||||
};
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
|
||||
@@ -21,12 +21,12 @@ public class ResponseWithBodyTests
|
||||
|
||||
private readonly Mock<IMapping> _mappingMock;
|
||||
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
||||
private readonly WireMockServerSettings _settings = new ();
|
||||
private readonly WireMockServerSettings _settings = new();
|
||||
|
||||
public ResponseWithBodyTests()
|
||||
{
|
||||
_mappingMock = new Mock<IMapping>();
|
||||
|
||||
|
||||
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||
|
||||
@@ -197,61 +197,7 @@ public class ResponseWithBodyTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBody_Func()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp);
|
||||
|
||||
var responseBuilder = Response.Create()
|
||||
.WithStatusCode(500)
|
||||
.WithHeader("H1", "X1")
|
||||
.WithHeader("H2", "X2")
|
||||
.WithBody(req => $"path: {req.Path}");
|
||||
|
||||
// Act
|
||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("path: /test");
|
||||
Check.That(response.Message.BodyData.BodyAsBytes).IsNull();
|
||||
Check.That(response.Message.BodyData.BodyAsJson).IsNull();
|
||||
Check.That(response.Message.BodyData.Encoding.CodePage).Equals(Encoding.UTF8.CodePage);
|
||||
Check.That(response.Message.StatusCode).IsEqualTo(500);
|
||||
Check.That(response.Message.Headers["H1"].ToString()).IsEqualTo("X1");
|
||||
Check.That(response.Message.Headers["H2"].ToString()).IsEqualTo("X2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBody_FuncAsync()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp);
|
||||
|
||||
var responseBuilder = Response.Create()
|
||||
.WithStatusCode(500)
|
||||
.WithHeader("H1", "X1")
|
||||
.WithHeader("H2", "X2")
|
||||
.WithBody(async req =>
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
return $"path: {req.Path}";
|
||||
});
|
||||
|
||||
// Act
|
||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("path: /test");
|
||||
Check.That(response.Message.BodyData.BodyAsBytes).IsNull();
|
||||
Check.That(response.Message.BodyData.BodyAsJson).IsNull();
|
||||
Check.That(response.Message.BodyData.Encoding.CodePage).Equals(Encoding.UTF8.CodePage);
|
||||
Check.That(response.Message.StatusCode).IsEqualTo(500);
|
||||
Check.That(response.Message.Headers["H1"].ToString()).IsEqualTo("X1");
|
||||
Check.That(response.Message.Headers["H2"].ToString()).IsEqualTo("X2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithJsonBodyAndTransform_Func()
|
||||
public async Task Response_ProvideResponse_WithJsonBodyAndTransform()
|
||||
{
|
||||
// Assign
|
||||
const int request1Id = 1;
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NFluent;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
@@ -18,17 +20,124 @@ public class ResponseWithCallbackTests
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
private readonly Mock<IMapping> _mappingMock;
|
||||
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
||||
private readonly WireMockServerSettings _settings = new();
|
||||
|
||||
public ResponseWithCallbackTests()
|
||||
{
|
||||
_mappingMock = new Mock<IMapping>();
|
||||
|
||||
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||
|
||||
_settings.FileSystemHandler = _filesystemHandlerMock.Object;
|
||||
_settings.FileSystemHandler = filesystemHandlerMock.Object;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBody_Func()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp);
|
||||
|
||||
var responseBuilder = Response.Create()
|
||||
.WithStatusCode(500)
|
||||
.WithHeader("H1", "X1")
|
||||
.WithHeader("H2", "X2")
|
||||
.WithBody(req => $"path: {req.Path}");
|
||||
|
||||
// Act
|
||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("path: /test");
|
||||
Check.That(response.Message.BodyData.BodyAsBytes).IsNull();
|
||||
Check.That(response.Message.BodyData.BodyAsJson).IsNull();
|
||||
Check.That(response.Message.BodyData.Encoding.CodePage).Equals(Encoding.UTF8.CodePage);
|
||||
Check.That(response.Message.StatusCode).IsEqualTo(500);
|
||||
Check.That(response.Message.Headers["H1"].ToString()).IsEqualTo("X1");
|
||||
Check.That(response.Message.Headers["H2"].ToString()).IsEqualTo("X2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBody_Func_DynamicCode_Should_IsFuncUsed()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp);
|
||||
|
||||
var data = new[] { "x", "y" };
|
||||
var i = 0;
|
||||
var responseBuilder = Response.Create()
|
||||
.WithBody(_ =>
|
||||
{
|
||||
var value = data[i];
|
||||
i++;
|
||||
return value;
|
||||
});
|
||||
|
||||
// Act (2x)
|
||||
var response1 = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
var response2 = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
response1.Message.BodyData!.BodyAsString.Should().Be("x");
|
||||
response1.Message.BodyData!.IsFuncUsed.Should().Be("Func<IRequestMessage, string>");
|
||||
response2.Message.BodyData!.BodyAsString.Should().Be("y");
|
||||
response2.Message.BodyData!.IsFuncUsed.Should().Be("Func<IRequestMessage, string>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBody_AsyncFunc_DynamicCode_Should_IsFuncUsed()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp);
|
||||
|
||||
var data = new[] { "x", "y" };
|
||||
var i = 0;
|
||||
var responseBuilder = Response.Create()
|
||||
.WithBody(_ =>
|
||||
{
|
||||
var value = data[i];
|
||||
i++;
|
||||
return Task.FromResult(value);
|
||||
});
|
||||
|
||||
// Act (2x)
|
||||
var response1 = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
var response2 = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
response1.Message.BodyData!.BodyAsString.Should().Be("x");
|
||||
response1.Message.BodyData!.IsFuncUsed.Should().Be("Func<IRequestMessage, Task<string>>");
|
||||
response2.Message.BodyData!.BodyAsString.Should().Be("y");
|
||||
response2.Message.BodyData!.IsFuncUsed.Should().Be("Func<IRequestMessage, Task<string>>");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_WithBody_FuncAsync()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/test"), "GET", ClientIp);
|
||||
|
||||
var responseBuilder = Response.Create()
|
||||
.WithStatusCode(500)
|
||||
.WithHeader("H1", "X1")
|
||||
.WithHeader("H2", "X2")
|
||||
.WithBody(async req =>
|
||||
{
|
||||
await Task.Delay(1).ConfigureAwait(false);
|
||||
return $"path: {req.Path}";
|
||||
});
|
||||
|
||||
// Act
|
||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
Check.That(response.Message.BodyData.BodyAsString).IsEqualTo("path: /test");
|
||||
Check.That(response.Message.BodyData.BodyAsBytes).IsNull();
|
||||
Check.That(response.Message.BodyData.BodyAsJson).IsNull();
|
||||
Check.That(response.Message.BodyData.Encoding.CodePage).Equals(Encoding.UTF8.CodePage);
|
||||
Check.That(response.Message.StatusCode).IsEqualTo(500);
|
||||
Check.That(response.Message.Headers["H1"].ToString()).IsEqualTo("X1");
|
||||
Check.That(response.Message.Headers["H2"].ToString()).IsEqualTo("X2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -2,6 +2,7 @@ using FluentAssertions;
|
||||
using NFluent;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Models;
|
||||
using WireMock.Owin;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Types;
|
||||
@@ -12,6 +13,15 @@ namespace WireMock.Net.Tests.Serialization;
|
||||
|
||||
public class LogEntryMapperTests
|
||||
{
|
||||
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
|
||||
|
||||
private readonly LogEntryMapper _sut;
|
||||
|
||||
public LogEntryMapperTests()
|
||||
{
|
||||
_sut = new LogEntryMapper(_options);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogEntryMapper_Map_LogEntry_Check_BodyTypeBytes()
|
||||
{
|
||||
@@ -39,7 +49,7 @@ public class LogEntryMapperTests
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = LogEntryMapper.Map(logEntry);
|
||||
var result = _sut.Map(logEntry);
|
||||
|
||||
// Assert
|
||||
Check.That(result.Request.DetectedBodyType).IsEqualTo("Bytes");
|
||||
@@ -74,7 +84,7 @@ public class LogEntryMapperTests
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = LogEntryMapper.Map(logEntry);
|
||||
var result = _sut.Map(logEntry);
|
||||
|
||||
// Assert
|
||||
Check.That(result.Request.DetectedBodyType).IsNull();
|
||||
@@ -111,10 +121,49 @@ public class LogEntryMapperTests
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = LogEntryMapper.Map(logEntry);
|
||||
var result = _sut.Map(logEntry);
|
||||
|
||||
// Assert
|
||||
result.Response.FaultType.Should().Be("EMPTY_RESPONSE");
|
||||
result.Response.FaultPercentage.Should().Be(0.5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LogEntryMapper_Map_LogEntry_WhenFuncIsUsed_And_DoNotSaveDynamicResponseInLogEntry_Is_True_Should_NotSave_StringResponse()
|
||||
{
|
||||
// Assign
|
||||
var options = new WireMockMiddlewareOptions
|
||||
{
|
||||
DoNotSaveDynamicResponseInLogEntry = true
|
||||
};
|
||||
var isFuncUsed = "Func<IRequestMessage, string>";
|
||||
var logEntry = new LogEntry
|
||||
{
|
||||
RequestMessage = new RequestMessage(
|
||||
new UrlDetails("http://localhost"),
|
||||
"post",
|
||||
"::1",
|
||||
new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.Bytes,
|
||||
BodyAsBytes = new byte[] { 0 }
|
||||
}
|
||||
),
|
||||
ResponseMessage = new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = "test",
|
||||
IsFuncUsed = isFuncUsed
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = new LogEntryMapper(options).Map(logEntry);
|
||||
|
||||
// Assert
|
||||
result.Response.Body.Should().Be(isFuncUsed);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user