mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-19 07:54:53 +01:00
Add support to use 'mapping' object in in reponse templating (#798)
* mapping * . * .
This commit is contained in:
@@ -25,9 +25,10 @@ internal class WebhookSender
|
||||
_settings = Guard.NotNull(settings);
|
||||
}
|
||||
|
||||
public Task<HttpResponseMessage> SendAsync(HttpClient client, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
|
||||
public Task<HttpResponseMessage> SendAsync(HttpClient client, IMapping mapping, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
|
||||
{
|
||||
Guard.NotNull(client);
|
||||
Guard.NotNull(mapping);
|
||||
Guard.NotNull(request);
|
||||
Guard.NotNull(originalRequestMessage);
|
||||
Guard.NotNull(originalResponseMessage);
|
||||
@@ -54,7 +55,7 @@ internal class WebhookSender
|
||||
throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
(bodyData, headers) = responseMessageTransformer.Transform(originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers, request.TransformerReplaceNodeOptions);
|
||||
(bodyData, headers) = responseMessageTransformer.Transform(mapping, originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers, request.TransformerReplaceNodeOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -15,14 +15,14 @@ public class Mapping : IMapping
|
||||
/// <inheritdoc />
|
||||
public Guid Guid { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Title { get; }
|
||||
/// <inheritdoc />
|
||||
public string? Title { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Description { get; }
|
||||
/// <inheritdoc />
|
||||
public string? Description { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Path { get; set; }
|
||||
/// <inheritdoc />
|
||||
public string? Path { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
@@ -115,16 +115,16 @@ public class Mapping : IMapping
|
||||
TimeSettings = timeSettings;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
|
||||
{
|
||||
return Provider.ProvideResponseAsync(requestMessage, Settings);
|
||||
}
|
||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
|
||||
{
|
||||
return Provider.ProvideResponseAsync(this, requestMessage, Settings);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
|
||||
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
|
||||
{
|
||||
var result = new RequestMatchResult();
|
||||
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
|
||||
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
|
||||
{
|
||||
var result = new RequestMatchResult();
|
||||
|
||||
RequestMatcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@ using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Util;
|
||||
using WireMock.Types;
|
||||
#if !USE_ASPNETCORE
|
||||
using Owin;
|
||||
#else
|
||||
using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.Types;
|
||||
#endif
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace WireMock.Owin
|
||||
{
|
||||
internal class WireMockMiddleware : OwinMiddleware
|
||||
{
|
||||
private readonly object _lock = new object();
|
||||
private readonly object _lock = new();
|
||||
private static readonly Task CompletedTask = Task.FromResult(false);
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly IOwinRequestMapper _requestMapper;
|
||||
@@ -108,10 +108,10 @@ namespace WireMock.Owin
|
||||
|
||||
logRequest = targetMapping.LogMapping;
|
||||
|
||||
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null)
|
||||
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null && request.Headers != null)
|
||||
{
|
||||
bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList<string> authorization);
|
||||
if (!present || _options.AuthenticationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
|
||||
if (!present || _options.AuthenticationMatcher.IsMatch(authorization!.ToString()) < MatchScores.Perfect)
|
||||
{
|
||||
_options.Logger.Error("HttpStatusCode set to 401");
|
||||
response = ResponseMessageBuilder.Create(null, HttpStatusCode.Unauthorized);
|
||||
@@ -208,7 +208,7 @@ namespace WireMock.Owin
|
||||
|
||||
try
|
||||
{
|
||||
await webhookSender.SendAsync(httpClientForWebhook, mapping.Webhooks[index].Request, request, response).ConfigureAwait(false);
|
||||
await webhookSender.SendAsync(httpClientForWebhook, mapping, mapping.Webhooks[index].Request, request, response).ConfigureAwait(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -244,7 +244,7 @@ public partial class Response : IResponseBuilder
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
{
|
||||
Guard.NotNull(requestMessage);
|
||||
Guard.NotNull(settings);
|
||||
@@ -327,7 +327,7 @@ public partial class Response : IResponseBuilder
|
||||
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
return (responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
return (responseMessageTransformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
}
|
||||
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
||||
|
||||
@@ -13,7 +13,7 @@ internal class DynamicAsyncResponseProvider : IResponseProvider
|
||||
_responseMessageFunc = responseMessageFunc;
|
||||
}
|
||||
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
{
|
||||
return (await _responseMessageFunc(requestMessage).ConfigureAwait(false), null);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ internal class DynamicResponseProvider : IResponseProvider
|
||||
_responseMessageFunc = responseMessageFunc;
|
||||
}
|
||||
|
||||
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
{
|
||||
(IResponseMessage responseMessage, IMapping? mapping) result = (_responseMessageFunc(requestMessage), null);
|
||||
return Task.FromResult(result);
|
||||
|
||||
@@ -13,8 +13,9 @@ public interface IResponseProvider
|
||||
/// <summary>
|
||||
/// The provide response.
|
||||
/// </summary>
|
||||
/// <param name="mapping">The used mapping.</param>
|
||||
/// <param name="requestMessage">The request.</param>
|
||||
/// <param name="settings">The WireMockServerSettings.</param>
|
||||
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
|
||||
Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings);
|
||||
Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings);
|
||||
}
|
||||
@@ -15,7 +15,7 @@ internal class ProxyAsyncResponseProvider : IResponseProvider
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IMapping mapping, IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
{
|
||||
return (await _responseMessageFunc(requestMessage, _settings).ConfigureAwait(false), null);
|
||||
}
|
||||
|
||||
@@ -1,33 +1,32 @@
|
||||
namespace WireMock
|
||||
namespace WireMock;
|
||||
|
||||
/// <summary>
|
||||
/// The ScenarioState
|
||||
/// </summary>
|
||||
public class ScenarioState
|
||||
{
|
||||
/// <summary>
|
||||
/// The ScenarioState
|
||||
/// Gets or sets the Name (from the Scenario).
|
||||
/// </summary>
|
||||
public class ScenarioState
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Name (from the Scenario).
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the NextState.
|
||||
/// </summary>
|
||||
public string NextState { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the NextState.
|
||||
/// </summary>
|
||||
public string? NextState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is started.
|
||||
/// </summary>
|
||||
public bool Started { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is started.
|
||||
/// </summary>
|
||||
public bool Started { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is finished.
|
||||
/// </summary>
|
||||
public bool Finished { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="ScenarioState"/> is finished.
|
||||
/// </summary>
|
||||
public bool Finished { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the state counter.
|
||||
/// </summary>
|
||||
public int Counter { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the state counter.
|
||||
/// </summary>
|
||||
public int Counter { get; set; }
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public static class WireMockServerSettingsParser
|
||||
[PublicAPI]
|
||||
public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out WireMockServerSettings? settings, IWireMockLogger? logger = null)
|
||||
{
|
||||
Guard.HasNoNulls(args, nameof(args));
|
||||
Guard.HasNoNulls(args);
|
||||
|
||||
var parser = new SimpleCommandLineParser();
|
||||
parser.Parse(args);
|
||||
@@ -68,8 +68,7 @@ public static class WireMockServerSettingsParser
|
||||
{
|
||||
settings.Logger = logger;
|
||||
}
|
||||
|
||||
if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
|
||||
else if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
|
||||
{
|
||||
settings.Logger = new WireMockConsoleLogger();
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace WireMock.Transformers;
|
||||
|
||||
interface ITransformer
|
||||
{
|
||||
ResponseMessage Transform(IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
|
||||
ResponseMessage Transform(IMapping mapping, IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
|
||||
|
||||
(IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform(IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, IDictionary<string, WireMockList<string>>? headers, ReplaceNodeOptions options);
|
||||
(IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, IDictionary<string, WireMockList<string>>? headers, ReplaceNodeOptions options);
|
||||
}
|
||||
@@ -19,6 +19,7 @@ internal class Transformer : ITransformer
|
||||
}
|
||||
|
||||
public (IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform(
|
||||
IMapping mapping,
|
||||
IRequestMessage originalRequestMessage,
|
||||
IResponseMessage originalResponseMessage,
|
||||
IBodyData? bodyData,
|
||||
@@ -29,6 +30,7 @@ internal class Transformer : ITransformer
|
||||
|
||||
var model = new
|
||||
{
|
||||
mapping,
|
||||
request = originalRequestMessage,
|
||||
response = originalResponseMessage
|
||||
};
|
||||
@@ -42,7 +44,7 @@ internal class Transformer : ITransformer
|
||||
return (newBodyData, TransformHeaders(transformerContext, model, headers));
|
||||
}
|
||||
|
||||
public ResponseMessage Transform(IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
|
||||
public ResponseMessage Transform(IMapping mapping, IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
|
||||
{
|
||||
var transformerContext = _factory.Create();
|
||||
|
||||
@@ -50,6 +52,7 @@ internal class Transformer : ITransformer
|
||||
|
||||
var model = new
|
||||
{
|
||||
mapping,
|
||||
request = requestMessage
|
||||
};
|
||||
|
||||
@@ -82,22 +85,15 @@ internal class Transformer : ITransformer
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
private static IBodyData TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||
private static IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||
{
|
||||
switch (original?.DetectedBodyType)
|
||||
return original.DetectedBodyType switch
|
||||
{
|
||||
case BodyType.Json:
|
||||
return TransformBodyAsJson(transformerContext, options, model, original);
|
||||
|
||||
case BodyType.File:
|
||||
return TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile);
|
||||
|
||||
case BodyType.String:
|
||||
return TransformBodyAsString(transformerContext, model, original);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
BodyType.Json => TransformBodyAsJson(transformerContext, options, model, original),
|
||||
BodyType.File => TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile),
|
||||
BodyType.String => TransformBodyAsString(transformerContext, model, original),
|
||||
_ => null
|
||||
};
|
||||
}
|
||||
|
||||
private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, object model, IDictionary<string, WireMockList<string>>? original)
|
||||
@@ -166,11 +162,17 @@ internal class Transformer : ITransformer
|
||||
{
|
||||
const string property = "_";
|
||||
JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
|
||||
JToken node = dummy[property];
|
||||
if (dummy[property] == null)
|
||||
{
|
||||
// TODO: check if just returning null is fine
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
JToken node = dummy[property]!;
|
||||
|
||||
ReplaceNodeValue(options, node, transformedString);
|
||||
|
||||
return dummy[property];
|
||||
return dummy[property]!;
|
||||
}
|
||||
|
||||
return stringValue;
|
||||
|
||||
Reference in New Issue
Block a user