mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-24 01:35:07 +01:00
log
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -9,6 +9,7 @@ using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Owin.Mappers;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Services;
|
||||
using WireMock.Util;
|
||||
|
||||
@@ -66,6 +67,8 @@ internal partial class AspNetCoreSelfHost
|
||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||
services.AddSingleton<IGuidUtils, GuidUtils>();
|
||||
services.AddSingleton<LogEntryMapper>();
|
||||
services.AddSingleton<IWireMockMiddlewareLogger, WireMockMiddlewareLogger>();
|
||||
|
||||
#if NET8_0_OR_GREATER
|
||||
AddCors(services);
|
||||
|
||||
10
src/WireMock.Net.Minimal/Owin/IWireMockMiddlewareLogger.cs
Normal file
10
src/WireMock.Net.Minimal/Owin/IWireMockMiddlewareLogger.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal interface IWireMockMiddlewareLogger
|
||||
{
|
||||
void Log(bool logRequest, RequestMessage request, IResponseMessage? response, MappingMatcherResult? match, MappingMatcherResult? partialMatch, Activity? activity);
|
||||
}
|
||||
@@ -1,58 +1,34 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Http;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
using WireMock.Owin.Mappers;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using System.Diagnostics;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class WireMockMiddleware
|
||||
internal class WireMockMiddleware(
|
||||
RequestDelegate next,
|
||||
IWireMockMiddlewareOptions options,
|
||||
IOwinRequestMapper requestMapper,
|
||||
IOwinResponseMapper responseMapper,
|
||||
IMappingMatcher mappingMatcher,
|
||||
IWireMockMiddlewareLogger logger
|
||||
)
|
||||
{
|
||||
private readonly object _lock = new();
|
||||
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly IOwinRequestMapper _requestMapper;
|
||||
private readonly IOwinResponseMapper _responseMapper;
|
||||
private readonly IMappingMatcher _mappingMatcher;
|
||||
private readonly LogEntryMapper _logEntryMapper;
|
||||
private readonly IGuidUtils _guidUtils;
|
||||
|
||||
public WireMockMiddleware(
|
||||
RequestDelegate next,
|
||||
IWireMockMiddlewareOptions options,
|
||||
IOwinRequestMapper requestMapper,
|
||||
IOwinResponseMapper responseMapper,
|
||||
IMappingMatcher mappingMatcher,
|
||||
IGuidUtils guidUtils
|
||||
)
|
||||
{
|
||||
_options = Guard.NotNull(options);
|
||||
_requestMapper = Guard.NotNull(requestMapper);
|
||||
_responseMapper = Guard.NotNull(responseMapper);
|
||||
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
||||
_logEntryMapper = new LogEntryMapper(options);
|
||||
_guidUtils = Guard.NotNull(guidUtils);
|
||||
}
|
||||
|
||||
public Task Invoke(HttpContext ctx)
|
||||
{
|
||||
if (_options.HandleRequestsSynchronously.GetValueOrDefault(false))
|
||||
if (options.HandleRequestsSynchronously.GetValueOrDefault(false))
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
@@ -66,16 +42,16 @@ internal class WireMockMiddleware
|
||||
private async Task InvokeInternalAsync(HttpContext ctx)
|
||||
{
|
||||
// Store options in HttpContext for providers to access (e.g., WebSocketResponseProvider)
|
||||
ctx.Items[nameof(WireMockMiddlewareOptions)] = _options;
|
||||
ctx.Items[nameof(WireMockMiddlewareOptions)] = options;
|
||||
|
||||
var request = await _requestMapper.MapAsync(ctx, _options).ConfigureAwait(false);
|
||||
var request = await requestMapper.MapAsync(ctx, options).ConfigureAwait(false);
|
||||
|
||||
var logRequest = false;
|
||||
IResponseMessage? response = null;
|
||||
(MappingMatcherResult? Match, MappingMatcherResult? Partial) result = (null, null);
|
||||
|
||||
var tracingEnabled = _options.ActivityTracingOptions is not null;
|
||||
var excludeAdmin = _options.ActivityTracingOptions?.ExcludeAdminRequests ?? true;
|
||||
var tracingEnabled = options.ActivityTracingOptions is not null;
|
||||
var excludeAdmin = options.ActivityTracingOptions?.ExcludeAdminRequests ?? true;
|
||||
Activity? activity = null;
|
||||
|
||||
// Check if we should trace this request (optionally exclude admin requests)
|
||||
@@ -84,12 +60,12 @@ internal class WireMockMiddleware
|
||||
if (shouldTrace)
|
||||
{
|
||||
activity = WireMockActivitySource.StartRequestActivity(request.Method, request.Path);
|
||||
WireMockActivitySource.EnrichWithRequest(activity, request, _options.ActivityTracingOptions);
|
||||
WireMockActivitySource.EnrichWithRequest(activity, request, options.ActivityTracingOptions);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var mapping in _options.Mappings.Values)
|
||||
foreach (var mapping in options.Mappings.Values)
|
||||
{
|
||||
if (mapping.Scenario is null)
|
||||
{
|
||||
@@ -97,50 +73,50 @@ internal class WireMockMiddleware
|
||||
}
|
||||
|
||||
// Set scenario start
|
||||
if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
|
||||
if (!options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
|
||||
{
|
||||
_options.Scenarios.TryAdd(mapping.Scenario, new ScenarioState
|
||||
options.Scenarios.TryAdd(mapping.Scenario, new ScenarioState
|
||||
{
|
||||
Name = mapping.Scenario
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
result = _mappingMatcher.FindBestMatch(request);
|
||||
result = mappingMatcher.FindBestMatch(request);
|
||||
|
||||
var targetMapping = result.Match?.Mapping;
|
||||
if (targetMapping == null)
|
||||
{
|
||||
logRequest = true;
|
||||
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
|
||||
options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
|
||||
response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
||||
return;
|
||||
}
|
||||
|
||||
logRequest = targetMapping.LogMapping;
|
||||
|
||||
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null && request.Headers != null)
|
||||
if (targetMapping.IsAdminInterface && options.AuthenticationMatcher != null && request.Headers != null)
|
||||
{
|
||||
var authorizationHeaderPresent = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out var authorization);
|
||||
if (!authorizationHeaderPresent)
|
||||
{
|
||||
_options.Logger.Error("HttpStatusCode set to 401, authorization header is missing.");
|
||||
options.Logger.Error("HttpStatusCode set to 401, authorization header is missing.");
|
||||
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
|
||||
return;
|
||||
}
|
||||
|
||||
var authorizationHeaderMatchResult = _options.AuthenticationMatcher.IsMatch(authorization!.ToString());
|
||||
var authorizationHeaderMatchResult = options.AuthenticationMatcher.IsMatch(authorization!.ToString());
|
||||
if (!MatchScores.IsPerfect(authorizationHeaderMatchResult.Score))
|
||||
{
|
||||
_options.Logger.Error("HttpStatusCode set to 401, authentication failed.", authorizationHeaderMatchResult.Exception ?? throw new WireMockException("Authentication failed"));
|
||||
options.Logger.Error("HttpStatusCode set to 401, authentication failed.", authorizationHeaderMatchResult.Exception ?? throw new WireMockException("Authentication failed"));
|
||||
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetMapping.IsAdminInterface && _options.RequestProcessingDelay > TimeSpan.Zero)
|
||||
if (!targetMapping.IsAdminInterface && options.RequestProcessingDelay > TimeSpan.Zero)
|
||||
{
|
||||
await Task.Delay(_options.RequestProcessingDelay.Value).ConfigureAwait(false);
|
||||
await Task.Delay(options.RequestProcessingDelay.Value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
var (theResponse, theOptionalNewMapping) = await targetMapping.ProvideResponseAsync(ctx, request).ConfigureAwait(false);
|
||||
@@ -150,7 +126,7 @@ internal class WireMockMiddleware
|
||||
{
|
||||
if (responseBuilder?.ProxyAndRecordSettings?.SaveMapping == true || targetMapping.Settings.ProxyAndRecordSettings?.SaveMapping == true)
|
||||
{
|
||||
_options.Mappings.TryAdd(theOptionalNewMapping.Guid, theOptionalNewMapping);
|
||||
options.Mappings.TryAdd(theOptionalNewMapping.Guid, theOptionalNewMapping);
|
||||
}
|
||||
|
||||
if (responseBuilder?.ProxyAndRecordSettings?.SaveMappingToFile == true || targetMapping.Settings.ProxyAndRecordSettings?.SaveMappingToFile == true)
|
||||
@@ -175,56 +151,25 @@ internal class WireMockMiddleware
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
|
||||
options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
|
||||
WireMockActivitySource.RecordException(activity, ex);
|
||||
|
||||
response = ResponseMessageBuilder.Create(500, ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
var log = new LogEntry
|
||||
{
|
||||
Guid = _guidUtils.NewGuid(),
|
||||
RequestMessage = request,
|
||||
ResponseMessage = response,
|
||||
|
||||
MappingGuid = result.Match?.Mapping?.Guid,
|
||||
MappingTitle = result.Match?.Mapping?.Title,
|
||||
RequestMatchResult = result.Match?.RequestMatchResult,
|
||||
|
||||
PartialMappingGuid = result.Partial?.Mapping?.Guid,
|
||||
PartialMappingTitle = result.Partial?.Mapping?.Title,
|
||||
PartialMatchResult = result.Partial?.RequestMatchResult
|
||||
};
|
||||
|
||||
WireMockActivitySource.EnrichWithLogEntry(activity, log, _options.ActivityTracingOptions);
|
||||
activity?.Dispose();
|
||||
|
||||
LogRequest(log, logRequest);
|
||||
logger.Log(logRequest, request, response, result.Match, result.Partial, activity);
|
||||
|
||||
try
|
||||
{
|
||||
if (_options.SaveUnmatchedRequests == true && result.Match?.RequestMatchResult is not { IsPerfectMatch: true })
|
||||
{
|
||||
var filename = $"{log.Guid}.LogEntry.json";
|
||||
_options.FileSystemHandler?.WriteUnmatchedRequest(filename, JsonUtils.Serialize(log));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Empty catch
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _responseMapper.MapAsync(response, ctx.Response).ConfigureAwait(false);
|
||||
await responseMapper.MapAsync(response, ctx.Response).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_options.Logger.Error("HttpStatusCode set to 404 : No matching mapping found", ex);
|
||||
options.Logger.Error("HttpStatusCode set to 404 : No matching mapping found", ex);
|
||||
|
||||
var notFoundResponse = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
||||
await _responseMapper.MapAsync(notFoundResponse, ctx.Response).ConfigureAwait(false);
|
||||
await responseMapper.MapAsync(notFoundResponse, ctx.Response).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -247,12 +192,12 @@ internal class WireMockMiddleware
|
||||
if (!result.IsSuccessStatusCode)
|
||||
{
|
||||
var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
_options.Logger.Warn($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. HttpStatusCode: {result.StatusCode} Content: {content}");
|
||||
options.Logger.Warn($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. HttpStatusCode: {result.StatusCode} Content: {content}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_options.Logger.Error($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. Exception: {ex}");
|
||||
options.Logger.Error($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. Exception: {ex}");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -280,7 +225,7 @@ internal class WireMockMiddleware
|
||||
|
||||
private void UpdateScenarioState(IMapping mapping)
|
||||
{
|
||||
var scenario = _options.Scenarios[mapping.Scenario!];
|
||||
var scenario = options.Scenarios[mapping.Scenario!];
|
||||
|
||||
// Increase the number of times this state has been executed
|
||||
scenario.Counter++;
|
||||
@@ -296,59 +241,4 @@ internal class WireMockMiddleware
|
||||
scenario.Started = true;
|
||||
scenario.Finished = mapping.NextState == null;
|
||||
}
|
||||
|
||||
private void LogRequest(LogEntry entry, bool addRequest)
|
||||
{
|
||||
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||
|
||||
// If addRequest is set to true and MaxRequestLogCount is null or does have a value greater than 0, try to add a new request log.
|
||||
if (addRequest && _options.MaxRequestLogCount is null or > 0)
|
||||
{
|
||||
TryAddLogEntry(entry);
|
||||
}
|
||||
|
||||
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
||||
if (_options.MaxRequestLogCount is > 0)
|
||||
{
|
||||
var logEntries = _options.LogEntries.ToList();
|
||||
foreach (var logEntry in logEntries.OrderBy(le => le.RequestMessage.DateTime).Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
||||
{
|
||||
TryRemoveLogEntry(logEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
||||
if (_options.RequestLogExpirationDuration is > 0)
|
||||
{
|
||||
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
||||
foreach (var logEntry in _options.LogEntries.ToList().Where(le => le.RequestMessage.DateTime < checkTime))
|
||||
{
|
||||
TryRemoveLogEntry(logEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TryAddLogEntry(LogEntry logEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
_options.LogEntries.Add(logEntry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exception (can happen during stress testing)
|
||||
}
|
||||
}
|
||||
|
||||
private void TryRemoveLogEntry(LogEntry logEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
_options.LogEntries.Remove(logEntry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exception (can happen during stress testing)
|
||||
}
|
||||
}
|
||||
}
|
||||
104
src/WireMock.Net.Minimal/Owin/WireMockMiddlewareLogger.cs
Normal file
104
src/WireMock.Net.Minimal/Owin/WireMockMiddlewareLogger.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Diagnostics;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Owin.ActivityTracing;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class WireMockMiddlewareLogger(IWireMockMiddlewareOptions _options, LogEntryMapper _logEntryMapper, IGuidUtils _guidUtils) : IWireMockMiddlewareLogger
|
||||
{
|
||||
public void Log(bool logRequest, RequestMessage request, IResponseMessage? response, MappingMatcherResult? match, MappingMatcherResult? partialMatch, Activity? activity)
|
||||
{
|
||||
var log = new LogEntry
|
||||
{
|
||||
Guid = _guidUtils.NewGuid(),
|
||||
RequestMessage = request,
|
||||
ResponseMessage = response ?? new ResponseMessage(),
|
||||
|
||||
MappingGuid = match?.Mapping?.Guid,
|
||||
MappingTitle = match?.Mapping?.Title,
|
||||
RequestMatchResult = match?.RequestMatchResult ?? new RequestMatchResult(),
|
||||
|
||||
PartialMappingGuid = partialMatch?.Mapping?.Guid,
|
||||
PartialMappingTitle = partialMatch?.Mapping?.Title,
|
||||
PartialMatchResult = partialMatch?.RequestMatchResult ?? new RequestMatchResult()
|
||||
};
|
||||
|
||||
WireMockActivitySource.EnrichWithLogEntry(activity, log, _options.ActivityTracingOptions);
|
||||
activity?.Dispose();
|
||||
|
||||
LogRequest(log, logRequest);
|
||||
|
||||
try
|
||||
{
|
||||
if (_options.SaveUnmatchedRequests == true && match?.RequestMatchResult is not { IsPerfectMatch: true })
|
||||
{
|
||||
var filename = $"{log.Guid}.LogEntry.json";
|
||||
_options.FileSystemHandler?.WriteUnmatchedRequest(filename, JsonUtils.Serialize(log));
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Empty catch
|
||||
}
|
||||
}
|
||||
|
||||
private void LogRequest(LogEntry entry, bool addRequest)
|
||||
{
|
||||
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||
|
||||
// If addRequest is set to true and MaxRequestLogCount is null or does have a value greater than 0, try to add a new request log.
|
||||
if (addRequest && _options.MaxRequestLogCount is null or > 0)
|
||||
{
|
||||
TryAddLogEntry(entry);
|
||||
}
|
||||
|
||||
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
||||
if (_options.MaxRequestLogCount is > 0)
|
||||
{
|
||||
var logEntries = _options.LogEntries.ToList();
|
||||
foreach (var logEntry in logEntries.OrderBy(le => le.RequestMessage.DateTime).Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
||||
{
|
||||
TryRemoveLogEntry(logEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
||||
if (_options.RequestLogExpirationDuration is > 0)
|
||||
{
|
||||
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
||||
foreach (var logEntry in _options.LogEntries.ToList().Where(le => le.RequestMessage.DateTime < checkTime))
|
||||
{
|
||||
TryRemoveLogEntry(logEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TryAddLogEntry(LogEntry logEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
_options.LogEntries.Add(logEntry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exception (can happen during stress testing)
|
||||
}
|
||||
}
|
||||
|
||||
private void TryRemoveLogEntry(LogEntry logEntry)
|
||||
{
|
||||
try
|
||||
{
|
||||
_options.LogEntries.Remove(logEntry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore exception (can happen during stress testing)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Admin.Requests;
|
||||
|
||||
@@ -250,7 +250,7 @@ internal class WebSocketBuilder(Response response) : IWebSocketBuilder
|
||||
Mapping = context.Mapping,
|
||||
Request = context.RequestMessage,
|
||||
Message = incomingMessage,
|
||||
Data = incomingMessage.MessageType == WebSocketMessageType.Text ? incomingMessage.Text : null
|
||||
Data = context.Mapping.Data
|
||||
};
|
||||
|
||||
return transformer.Transform(text, model);
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Net.WebSockets;
|
||||
|
||||
namespace WireMock.WebSockets;
|
||||
|
||||
@@ -23,7 +23,7 @@ internal struct WebSocketTransformModel
|
||||
public WebSocketMessage Message { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The message data as string
|
||||
/// The mapping data as object
|
||||
/// </summary>
|
||||
public string? Data { get; set; }
|
||||
}
|
||||
public object? Data { get; set; }
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Owin;
|
||||
|
||||
Reference in New Issue
Block a user