WebHook - Transform Url (#824)

* WebHook - Url

* .
This commit is contained in:
Stef Heyenrath
2022-10-15 08:55:05 +02:00
committed by GitHub
parent 55afc8041f
commit 36037627bc
6 changed files with 231 additions and 178 deletions

View File

@@ -0,0 +1,8 @@
{
"profiles": {
"WSL": {
"commandName": "WSL2",
"distributionName": ""
}
}
}

View File

@@ -44,37 +44,41 @@ internal class WebhookSender
IBodyData? bodyData; IBodyData? bodyData;
IDictionary<string, WireMockList<string>>? headers; IDictionary<string, WireMockList<string>>? headers;
string webhookRequestUrl;
if (webhookRequest.UseTransformer == true) if (webhookRequest.UseTransformer == true)
{ {
ITransformer responseMessageTransformer; ITransformer transformer;
switch (webhookRequest.TransformerType) switch (webhookRequest.TransformerType)
{ {
case TransformerType.Handlebars: case TransformerType.Handlebars:
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback); var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
responseMessageTransformer = new Transformer(factoryHandlebars); transformer = new Transformer(factoryHandlebars);
break; break;
case TransformerType.Scriban: case TransformerType.Scriban:
case TransformerType.ScribanDotLiquid: case TransformerType.ScribanDotLiquid:
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType); var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
responseMessageTransformer = new Transformer(factoryDotLiquid); transformer = new Transformer(factoryDotLiquid);
break; break;
default: default:
throw new NotImplementedException($"TransformerType '{webhookRequest.TransformerType}' is not supported."); throw new NotImplementedException($"TransformerType '{webhookRequest.TransformerType}' is not supported.");
} }
(bodyData, headers) = responseMessageTransformer.Transform(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.BodyData, webhookRequest.Headers, webhookRequest.TransformerReplaceNodeOptions); bodyData = transformer.TransformBody(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.BodyData, webhookRequest.TransformerReplaceNodeOptions);
headers = transformer.TransformHeaders(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Headers);
webhookRequestUrl = transformer.TransformString(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Url);
} }
else else
{ {
bodyData = webhookRequest.BodyData; bodyData = webhookRequest.BodyData;
headers = webhookRequest.Headers; headers = webhookRequest.Headers;
webhookRequestUrl = webhookRequest.Url;
} }
// Create RequestMessage // Create RequestMessage
var requestMessage = new RequestMessage( var requestMessage = new RequestMessage(
new UrlDetails(webhookRequest.Url), new UrlDetails(webhookRequestUrl),
webhookRequest.Method, webhookRequest.Method,
ClientIp, ClientIp,
bodyData, bodyData,

View File

@@ -8,5 +8,9 @@ interface ITransformer
{ {
ResponseMessage Transform(IMapping mapping, 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(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, IDictionary<string, WireMockList<string>>? headers, ReplaceNodeOptions options); IBodyData? TransformBody(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, ReplaceNodeOptions options);
IDictionary<string, WireMockList<string>>? TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary<string, WireMockList<string>>? headers);
string TransformString(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, string? value);
} }

View File

@@ -0,0 +1,13 @@
using System.Diagnostics.CodeAnalysis;
namespace WireMock.Transformers;
[SuppressMessage("ReSharper", "InconsistentNaming")]
internal struct TransformModel
{
public IMapping mapping { get; set; }
public IRequestMessage request { get; set; }
public IResponseMessage? response { get; set; }
}

View File

@@ -1,9 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Stef.Validation; using Stef.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
@@ -18,22 +18,14 @@ internal class Transformer : ITransformer
_factory = Guard.NotNull(factory); _factory = Guard.NotNull(factory);
} }
public (IBodyData? BodyData, IDictionary<string, WireMockList<string>>? Headers) Transform( public IBodyData? TransformBody(
IMapping mapping, IMapping mapping,
IRequestMessage originalRequestMessage, IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage, IResponseMessage originalResponseMessage,
IBodyData? bodyData, IBodyData? bodyData,
IDictionary<string, WireMockList<string>>? headers,
ReplaceNodeOptions options) ReplaceNodeOptions options)
{ {
var transformerContext = _factory.Create(); var (transformerContext, model) = Create(mapping, originalRequestMessage, originalResponseMessage);
var model = new
{
mapping,
request = originalRequestMessage,
response = originalResponseMessage
};
IBodyData? newBodyData = null; IBodyData? newBodyData = null;
if (bodyData?.DetectedBodyType != null) if (bodyData?.DetectedBodyType != null)
@@ -41,20 +33,42 @@ internal class Transformer : ITransformer
newBodyData = TransformBodyData(transformerContext, options, model, bodyData, false); newBodyData = TransformBodyData(transformerContext, options, model, bodyData, false);
} }
return (newBodyData, TransformHeaders(transformerContext, model, headers)); return newBodyData;
}
public IDictionary<string, WireMockList<string>>? TransformHeaders(
IMapping mapping,
IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage,
IDictionary<string, WireMockList<string>>? headers
)
{
var (transformerContext, model) = Create(mapping, originalRequestMessage, originalResponseMessage);
return TransformHeaders(transformerContext, model, headers);
}
public string TransformString(
IMapping mapping,
IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage,
string? value
)
{
if (value is null)
{
return string.Empty;
}
var (transformerContext, model) = Create(mapping, originalRequestMessage, originalResponseMessage);
return transformerContext.ParseAndRender(value, model);
} }
public ResponseMessage Transform(IMapping mapping, 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();
var responseMessage = new ResponseMessage(); var responseMessage = new ResponseMessage();
var model = new var (transformerContext, model) = Create(mapping, requestMessage, null);
{
mapping,
request = requestMessage
};
if (original.BodyData?.DetectedBodyType != null) if (original.BodyData?.DetectedBodyType != null)
{ {
@@ -85,7 +99,17 @@ internal class Transformer : ITransformer
return responseMessage; return responseMessage;
} }
private static IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, object model, IBodyData original, bool useTransformerForBodyAsFile) private (ITransformerContext TransformerContext, TransformModel Model) Create(IMapping mapping, IRequestMessage request, IResponseMessage? response)
{
return (_factory.Create(), new TransformModel
{
mapping = mapping,
request = request,
response = response
});
}
private static IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, TransformModel model, IBodyData original, bool useTransformerForBodyAsFile)
{ {
return original.DetectedBodyType switch return original.DetectedBodyType switch
{ {
@@ -96,7 +120,7 @@ internal class Transformer : ITransformer
}; };
} }
private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, object model, IDictionary<string, WireMockList<string>>? original) private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, TransformModel model, IDictionary<string, WireMockList<string>>? original)
{ {
if (original == null) if (original == null)
{ {

View File

@@ -12,190 +12,190 @@ using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using Xunit; using Xunit;
namespace WireMock.Net.Tests namespace WireMock.Net.Tests;
public class WireMockServerWebhookTests
{ {
public class WireMockServerWebhookTests [Fact]
public async Task WireMockServer_WithWebhooks_Should_Send_Message_To_Webhooks()
{ {
[Fact] // Assign
public async Task WireMockServer_WithWebhooks_Should_Send_Message_To_Webhooks() var serverReceivingTheWebhook1 = WireMockServer.Start();
serverReceivingTheWebhook1.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200));
var serverReceivingTheWebhook2 = WireMockServer.Start();
serverReceivingTheWebhook2.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200));
var webhook1 = new Webhook
{ {
// Assign Request = new WebhookRequest
var serverReceivingTheWebhook1 = WireMockServer.Start(); {
serverReceivingTheWebhook1.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200)); Url = serverReceivingTheWebhook1.Urls[0],
Method = "post",
BodyData = new BodyData
{
BodyAsString = "1",
DetectedBodyType = BodyType.String,
DetectedBodyTypeFromContentType = BodyType.String
}
}
};
var serverReceivingTheWebhook2 = WireMockServer.Start(); var webhook2 = new Webhook
serverReceivingTheWebhook2.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200)); {
Request = new WebhookRequest
{
Url = serverReceivingTheWebhook2.Urls[0],
Method = "post",
BodyData = new BodyData
{
BodyAsString = "2",
DetectedBodyType = BodyType.String,
DetectedBodyTypeFromContentType = BodyType.String
}
}
};
var webhook1 = new Webhook // Act
var server = WireMockServer.Start();
server.Given(Request.Create().UsingPost())
.WithWebhook(webhook1, webhook2)
.RespondWith(Response.Create().WithBody("a-response"));
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri($"{server.Urls[0]}/TST"),
Content = new StringContent("test")
};
// Assert
var response = await new HttpClient().SendAsync(request).ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
response.StatusCode.Should().Be(HttpStatusCode.OK);
content.Should().Be("a-response");
serverReceivingTheWebhook1.LogEntries.Should().HaveCount(1);
serverReceivingTheWebhook2.LogEntries.Should().HaveCount(1);
server.Dispose();
serverReceivingTheWebhook1.Dispose();
serverReceivingTheWebhook2.Dispose();
}
[Fact]
public async Task WireMockServer_WithWebhook_Should_Send_Message_To_Webhook()
{
// Assign
var serverReceivingTheWebhook = WireMockServer.Start();
serverReceivingTheWebhook.Given(Request.Create().WithPath("x").UsingPost()).RespondWith(Response.Create().WithStatusCode(200));
// Act
var server = WireMockServer.Start();
server.Given(Request.Create().UsingPost())
.WithWebhook(new Webhook
{ {
Request = new WebhookRequest Request = new WebhookRequest
{ {
Url = serverReceivingTheWebhook1.Urls[0], Url = serverReceivingTheWebhook.Url! + "/{{request.Query.q}}",
Method = "post", Method = "post",
BodyData = new BodyData BodyData = new BodyData
{ {
BodyAsString = "1", BodyAsString = "abc",
DetectedBodyType = BodyType.String, DetectedBodyType = BodyType.String,
DetectedBodyTypeFromContentType = BodyType.String DetectedBodyTypeFromContentType = BodyType.String
} },
UseTransformer = true
} }
}; })
.RespondWith(Response.Create().WithBody("a-response"));
var webhook2 = new Webhook var request = new HttpRequestMessage
{
Request = new WebhookRequest
{
Url = serverReceivingTheWebhook2.Urls[0],
Method = "post",
BodyData = new BodyData
{
BodyAsString = "2",
DetectedBodyType = BodyType.String,
DetectedBodyTypeFromContentType = BodyType.String
}
}
};
// Act
var server = WireMockServer.Start();
server.Given(Request.Create().UsingPost())
.WithWebhook(webhook1, webhook2)
.RespondWith(Response.Create().WithBody("a-response"));
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri($"{server.Urls[0]}/TST"),
Content = new StringContent("test")
};
// Assert
var response = await new HttpClient().SendAsync(request).ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
response.StatusCode.Should().Be(HttpStatusCode.OK);
content.Should().Be("a-response");
serverReceivingTheWebhook1.LogEntries.Should().HaveCount(1);
serverReceivingTheWebhook2.LogEntries.Should().HaveCount(1);
server.Dispose();
serverReceivingTheWebhook1.Dispose();
serverReceivingTheWebhook2.Dispose();
}
[Fact]
public async Task WireMockServer_WithWebhook_Should_Send_Message_To_Webhook()
{ {
// Assign Method = HttpMethod.Post,
var serverReceivingTheWebhook = WireMockServer.Start(); RequestUri = new Uri($"{server.Urls[0]}/TST?q=x"),
serverReceivingTheWebhook.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200)); Content = new StringContent("test")
};
// Act // Assert
var server = WireMockServer.Start(); var response = await new HttpClient().SendAsync(request).ConfigureAwait(false);
server.Given(Request.Create().UsingPost()) string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
.WithWebhook(new Webhook
{
Request = new WebhookRequest
{
Url = serverReceivingTheWebhook.Urls[0],
Method = "post",
BodyData = new BodyData
{
BodyAsString = "abc",
DetectedBodyType = BodyType.String,
DetectedBodyTypeFromContentType = BodyType.String
}
}
})
.RespondWith(Response.Create().WithBody("a-response"));
var request = new HttpRequestMessage response.StatusCode.Should().Be(HttpStatusCode.OK);
{ content.Should().Be("a-response");
Method = HttpMethod.Post,
RequestUri = new Uri($"{server.Urls[0]}/TST"),
Content = new StringContent("test")
};
// Assert serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
var response = await new HttpClient().SendAsync(request).ConfigureAwait(false);
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
response.StatusCode.Should().Be(HttpStatusCode.OK); server.Dispose();
content.Should().Be("a-response"); serverReceivingTheWebhook.Dispose();
}
serverReceivingTheWebhook.LogEntries.Should().HaveCount(1); [Fact]
public async Task WireMockServer_WithWebhookArgs_Should_Send_StringMessage_To_Webhook()
{
// Assign
var serverReceivingTheWebhook = WireMockServer.Start();
serverReceivingTheWebhook.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200));
server.Dispose(); // Act
serverReceivingTheWebhook.Dispose(); var server = WireMockServer.Start();
} server.Given(Request.Create().UsingPost())
.WithWebhook(serverReceivingTheWebhook.Urls[0], "post", null, "OK !", true, TransformerType.Handlebars)
.RespondWith(Response.Create().WithBody("a-response"));
[Fact] var request = new HttpRequestMessage
public async Task WireMockServer_WithWebhookArgs_Should_Send_StringMessage_To_Webhook()
{ {
// Assign Method = HttpMethod.Post,
var serverReceivingTheWebhook = WireMockServer.Start(); RequestUri = new Uri($"{server.Urls[0]}/TST"),
serverReceivingTheWebhook.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200)); Content = new StringContent("test")
};
// Act // Assert
var server = WireMockServer.Start(); var response = await new HttpClient().SendAsync(request).ConfigureAwait(false);
server.Given(Request.Create().UsingPost()) string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
.WithWebhook(serverReceivingTheWebhook.Urls[0], "post", null, "OK !", true, TransformerType.Handlebars)
.RespondWith(Response.Create().WithBody("a-response"));
var request = new HttpRequestMessage response.StatusCode.Should().Be(HttpStatusCode.OK);
{ content.Should().Be("a-response");
Method = HttpMethod.Post,
RequestUri = new Uri($"{server.Urls[0]}/TST"),
Content = new StringContent("test")
};
// Assert serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
var response = await new HttpClient().SendAsync(request).ConfigureAwait(false); serverReceivingTheWebhook.LogEntries.First().RequestMessage.Body.Should().Be("OK !");
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
response.StatusCode.Should().Be(HttpStatusCode.OK); server.Dispose();
content.Should().Be("a-response"); serverReceivingTheWebhook.Dispose();
}
serverReceivingTheWebhook.LogEntries.Should().HaveCount(1); [Fact]
serverReceivingTheWebhook.LogEntries.First().RequestMessage.Body.Should().Be("OK !"); public async Task WireMockServer_WithWebhookArgs_Should_Send_JsonMessage_To_Webhook()
{
// Assign
var serverReceivingTheWebhook = WireMockServer.Start();
serverReceivingTheWebhook.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200));
server.Dispose(); // Act
serverReceivingTheWebhook.Dispose(); var server = WireMockServer.Start();
} server.Given(Request.Create().UsingPost())
.WithWebhook(serverReceivingTheWebhook.Urls[0], "post", null, new { Status = "OK" }, true, TransformerType.Handlebars)
.RespondWith(Response.Create().WithBody("a-response"));
[Fact] var request = new HttpRequestMessage
public async Task WireMockServer_WithWebhookArgs_Should_Send_JsonMessage_To_Webhook()
{ {
// Assign Method = HttpMethod.Post,
var serverReceivingTheWebhook = WireMockServer.Start(); RequestUri = new Uri($"{server.Urls[0]}/TST"),
serverReceivingTheWebhook.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200)); Content = new StringContent("test")
};
// Act // Assert
var server = WireMockServer.Start(); var response = await new HttpClient().SendAsync(request).ConfigureAwait(false);
server.Given(Request.Create().UsingPost()) string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
.WithWebhook(serverReceivingTheWebhook.Urls[0], "post", null, new { Status = "OK" }, true, TransformerType.Handlebars)
.RespondWith(Response.Create().WithBody("a-response"));
var request = new HttpRequestMessage response.StatusCode.Should().Be(HttpStatusCode.OK);
{ content.Should().Be("a-response");
Method = HttpMethod.Post,
RequestUri = new Uri($"{server.Urls[0]}/TST"),
Content = new StringContent("test")
};
// Assert serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
var response = await new HttpClient().SendAsync(request).ConfigureAwait(false); serverReceivingTheWebhook.LogEntries.First().RequestMessage.Body.Should().Be("{\"Status\":\"OK\"}");
string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
response.StatusCode.Should().Be(HttpStatusCode.OK); server.Dispose();
content.Should().Be("a-response"); serverReceivingTheWebhook.Dispose();
serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
serverReceivingTheWebhook.LogEntries.First().RequestMessage.Body.Should().Be("{\"Status\":\"OK\"}");
server.Dispose();
serverReceivingTheWebhook.Dispose();
}
} }
} }