mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-22 16:58:06 +01:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ad060bbd4 | ||
|
|
d758301e4f |
@@ -1,3 +1,7 @@
|
|||||||
|
# 1.4.8 (24 March 2021)
|
||||||
|
- [#591](https://github.com/WireMock-Net/WireMock.Net/pull/591) - Webhook [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#589](https://github.com/WireMock-Net/WireMock.Net/issues/589) - How to send a request to a specific URL after sending response [feature]
|
||||||
|
|
||||||
# 1.4.7 (21 March 2021)
|
# 1.4.7 (21 March 2021)
|
||||||
- [#594](https://github.com/WireMock-Net/WireMock.Net/pull/594) - Add possibility to the WithBody() to use IBodyData [feature] contributed by [StefH](https://github.com/StefH)
|
- [#594](https://github.com/WireMock-Net/WireMock.Net/pull/594) - Add possibility to the WithBody() to use IBodyData [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#595](https://github.com/WireMock-Net/WireMock.Net/pull/595) - Use Handlebars.Net.Helpers Version="2.1.2" [feature] contributed by [StefH](https://github.com/StefH)
|
- [#595](https://github.com/WireMock-Net/WireMock.Net/pull/595) - Use Handlebars.Net.Helpers Version="2.1.2" [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
@@ -48,7 +52,6 @@
|
|||||||
- [#549](https://github.com/WireMock-Net/WireMock.Net/issues/549) - WithProxy(...) does not save the mappings to file [bug]
|
- [#549](https://github.com/WireMock-Net/WireMock.Net/issues/549) - WithProxy(...) does not save the mappings to file [bug]
|
||||||
|
|
||||||
# 1.3.8 (03 December 2020)
|
# 1.3.8 (03 December 2020)
|
||||||
- [#539](https://github.com/WireMock-Net/WireMock.Net/pull/539) - Support for partial JSON matching contributed by [gleb-osokin](https://github.com/gleb-osokin)
|
|
||||||
- [#542](https://github.com/WireMock-Net/WireMock.Net/pull/542) - Create dotnet-wiremock tool [feature] contributed by [StefH](https://github.com/StefH)
|
- [#542](https://github.com/WireMock-Net/WireMock.Net/pull/542) - Create dotnet-wiremock tool [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#543](https://github.com/WireMock-Net/WireMock.Net/pull/543) - Add support for .NET 5 [feature] contributed by [StefH](https://github.com/StefH)
|
- [#543](https://github.com/WireMock-Net/WireMock.Net/pull/543) - Add support for .NET 5 [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#544](https://github.com/WireMock-Net/WireMock.Net/pull/544) - Use Java 11 in Azure Pipelines (needed for SonarCloud) [feature] contributed by [StefH](https://github.com/StefH)
|
- [#544](https://github.com/WireMock-Net/WireMock.Net/pull/544) - Use Java 11 in Azure Pipelines (needed for SonarCloud) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
@@ -56,6 +59,9 @@
|
|||||||
- [#547](https://github.com/WireMock-Net/WireMock.Net/pull/547) - Fix Proxying with SSL and NetCoreApp3.1 [bug] contributed by [StefH](https://github.com/StefH)
|
- [#547](https://github.com/WireMock-Net/WireMock.Net/pull/547) - Fix Proxying with SSL and NetCoreApp3.1 [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#524](https://github.com/WireMock-Net/WireMock.Net/issues/524) - Proxying with SSL Not Working in .NET Core 3.1 [bug]
|
- [#524](https://github.com/WireMock-Net/WireMock.Net/issues/524) - Proxying with SSL Not Working in .NET Core 3.1 [bug]
|
||||||
|
|
||||||
|
# 1.3.7 (17 November 2020)
|
||||||
|
- [#539](https://github.com/WireMock-Net/WireMock.Net/pull/539) - Support for partial JSON matching contributed by [gleb-osokin](https://github.com/gleb-osokin)
|
||||||
|
|
||||||
# 1.3.6 (10 November 2020)
|
# 1.3.6 (10 November 2020)
|
||||||
- [#529](https://github.com/WireMock-Net/WireMock.Net/pull/529) - Add assertions for ClientIP, Url and ProxyUrl [feature] contributed by [akamud](https://github.com/akamud)
|
- [#529](https://github.com/WireMock-Net/WireMock.Net/pull/529) - Add assertions for ClientIP, Url and ProxyUrl [feature] contributed by [akamud](https://github.com/akamud)
|
||||||
- [#535](https://github.com/WireMock-Net/WireMock.Net/pull/535) - WithCallback should use also use enum HttpStatusCode [bug] contributed by [StefH](https://github.com/StefH)
|
- [#535](https://github.com/WireMock-Net/WireMock.Net/pull/535) - WithCallback should use also use enum HttpStatusCode [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.4.7</VersionPrefix>
|
<VersionPrefix>1.4.8</VersionPrefix>
|
||||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||||
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
||||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
https://github.com/StefH/GitHubReleaseNotes
|
https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.4.7
|
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.4.8
|
||||||
@@ -1,40 +1,40 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using log4net;
|
using log4net;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
using log4net.Repository;
|
using log4net.Repository;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Net.StandAlone.NETCoreApp
|
namespace WireMock.Net.StandAlone.NETCoreApp
|
||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
||||||
// private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
// private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||||
|
|
||||||
private static int sleepTime = 30000;
|
private static int sleepTime = 30000;
|
||||||
private static WireMockServer _server;
|
private static WireMockServer _server;
|
||||||
|
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
||||||
|
|
||||||
if (!WireMockServerSettingsParser.TryParseArguments(args, out var settings, new WireMockLog4NetLogger()))
|
if (!WireMockServerSettingsParser.TryParseArguments(args, out var settings, new WireMockLog4NetLogger()))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||||
|
|
||||||
_server = WireMockServer.Start(settings);
|
_server = WireMockServer.Start(settings);
|
||||||
|
|
||||||
_server.Given(Request.Create().WithPath("/api/sap")
|
_server.Given(Request.Create().WithPath("/api/sap")
|
||||||
.UsingPost()
|
.UsingPost()
|
||||||
.WithBody((IBodyData xmlData) => {
|
.WithBody((IBodyData xmlData) => {
|
||||||
@@ -43,37 +43,37 @@ namespace WireMock.Net.StandAlone.NETCoreApp
|
|||||||
}))
|
}))
|
||||||
.RespondWith(Response.Create().WithStatusCode(System.Net.HttpStatusCode.OK));
|
.RespondWith(Response.Create().WithStatusCode(System.Net.HttpStatusCode.OK));
|
||||||
|
|
||||||
_server
|
_server
|
||||||
.Given(Request.Create()
|
.Given(Request.Create()
|
||||||
.UsingAnyMethod())
|
.UsingAnyMethod())
|
||||||
.RespondWith(Response.Create()
|
.RespondWith(Response.Create()
|
||||||
.WithTransformer()
|
.WithTransformer()
|
||||||
.WithBody("{{Random Type=\"Integer\" Min=100 Max=999999}} {{DateTime.Now}} {{DateTime.Now \"yyyy-MMM\"}} {{String.Format (DateTime.Now) \"MMM-dd\"}}"));
|
.WithBody("{{Random Type=\"Integer\" Min=100 Max=999999}} {{DateTime.Now}} {{DateTime.Now \"yyyy-MMM\"}} {{String.Format (DateTime.Now) \"MMM-dd\"}}"));
|
||||||
|
|
||||||
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
|
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
|
||||||
|
|
||||||
Console.CancelKeyPress += (s, e) =>
|
Console.CancelKeyPress += (s, e) =>
|
||||||
{
|
{
|
||||||
Stop("CancelKeyPress");
|
Stop("CancelKeyPress");
|
||||||
};
|
};
|
||||||
|
|
||||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += ctx =>
|
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += ctx =>
|
||||||
{
|
{
|
||||||
Stop("AssemblyLoadContext.Default.Unloading");
|
Stop("AssemblyLoadContext.Default.Unloading");
|
||||||
};
|
};
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server running : {_server.IsStarted}");
|
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server running : {_server.IsStarted}");
|
||||||
Thread.Sleep(sleepTime);
|
Thread.Sleep(sleepTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Stop(string why)
|
private static void Stop(string why)
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopping because '{why}'");
|
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopping because '{why}'");
|
||||||
_server.Stop();
|
_server.Stop();
|
||||||
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopped");
|
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopped");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"WireMock.Net.StandAlone.NETCoreApp": {
|
"WireMock.Net.StandAlone.NETCoreApp": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "--Urls https://localhost:10080 --WireMockLogger WireMockConsoleLogger"
|
"commandLineArgs": "--Urls http://localhost:9091 --WireMockLogger WireMockConsoleLogger"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,5 +52,10 @@ namespace WireMock.Admin.Mappings
|
|||||||
/// Saves this mapping as a static mapping file.
|
/// Saves this mapping as a static mapping file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? SaveToFile { get; set; }
|
public bool? SaveToFile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Webhook.
|
||||||
|
/// </summary>
|
||||||
|
public WebhookModel Webhook { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using WireMock.Types;
|
|
||||||
|
|
||||||
namespace WireMock.Admin.Mappings
|
namespace WireMock.Admin.Mappings
|
||||||
{
|
{
|
||||||
|
|||||||
13
src/WireMock.Net.Abstractions/Admin/Mappings/WebhookModel.cs
Normal file
13
src/WireMock.Net.Abstractions/Admin/Mappings/WebhookModel.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace WireMock.Admin.Mappings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Webhook
|
||||||
|
/// </summary>
|
||||||
|
public class WebhookModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Webhook Request.
|
||||||
|
/// </summary>
|
||||||
|
public WebhookRequestModel Request { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace WireMock.Admin.Mappings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// RequestModel
|
||||||
|
/// </summary>
|
||||||
|
public class WebhookRequestModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Url.
|
||||||
|
/// </summary>
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The methods
|
||||||
|
/// </summary>
|
||||||
|
public string Method { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the headers.
|
||||||
|
/// </summary>
|
||||||
|
public IDictionary<string, string> Headers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the body.
|
||||||
|
/// </summary>
|
||||||
|
public string Body { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the body (as JSON object).
|
||||||
|
/// </summary>
|
||||||
|
public object BodyAsJson { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use ResponseMessage Transformer.
|
||||||
|
/// </summary>
|
||||||
|
public bool? UseTransformer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the type of the transformer.
|
||||||
|
/// </summary>
|
||||||
|
public string TransformerType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
13
src/WireMock.Net.Abstractions/Models/IWebhook.cs
Normal file
13
src/WireMock.Net.Abstractions/Models/IWebhook.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace WireMock.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IWebhook
|
||||||
|
/// </summary>
|
||||||
|
public interface IWebhook
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Request
|
||||||
|
/// </summary>
|
||||||
|
IWebhookRequest Request { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/WireMock.Net.Abstractions/Models/IWebhookRequest.cs
Normal file
42
src/WireMock.Net.Abstractions/Models/IWebhookRequest.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
|
namespace WireMock.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IWebhookRequest
|
||||||
|
/// </summary>
|
||||||
|
public interface IWebhookRequest
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The Webhook Url.
|
||||||
|
/// </summary>
|
||||||
|
string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The method to use.
|
||||||
|
/// </summary>
|
||||||
|
string Method { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Headers to send.
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<string, WireMockList<string>> Headers { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The body to send.
|
||||||
|
/// </summary>
|
||||||
|
IBodyData BodyData { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use Transformer.
|
||||||
|
/// </summary>
|
||||||
|
bool? UseTransformer { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The transformer type.
|
||||||
|
/// </summary>
|
||||||
|
TransformerType TransformerType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ namespace WireMock.Http
|
|||||||
{
|
{
|
||||||
internal static class HttpClientBuilder
|
internal static class HttpClientBuilder
|
||||||
{
|
{
|
||||||
public static HttpClient Build(IProxyAndRecordSettings settings)
|
public static HttpClient Build(IHttpClientSettings settings)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD || NETCOREAPP3_1 || NET5_0
|
#if NETSTANDARD || NETCOREAPP3_1 || NET5_0
|
||||||
var handler = new HttpClientHandler
|
var handler = new HttpClientHandler
|
||||||
|
|||||||
85
src/WireMock.Net/Http/WebhookSender.cs
Normal file
85
src/WireMock.Net/Http/WebhookSender.cs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using WireMock.Models;
|
||||||
|
using WireMock.Settings;
|
||||||
|
using WireMock.Transformers;
|
||||||
|
using WireMock.Transformers.Handlebars;
|
||||||
|
using WireMock.Transformers.Scriban;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
using WireMock.Validation;
|
||||||
|
|
||||||
|
namespace WireMock.Http
|
||||||
|
{
|
||||||
|
internal class WebhookSender
|
||||||
|
{
|
||||||
|
private const string ClientIp = "::1";
|
||||||
|
|
||||||
|
private readonly IWireMockServerSettings _settings;
|
||||||
|
|
||||||
|
public WebhookSender(IWireMockServerSettings settings)
|
||||||
|
{
|
||||||
|
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<HttpResponseMessage> SendAsync([NotNull] HttpClient client, [NotNull] IWebhookRequest request, [NotNull] RequestMessage originalRequestMessage, [NotNull] ResponseMessage originalResponseMessage)
|
||||||
|
{
|
||||||
|
Check.NotNull(client, nameof(client));
|
||||||
|
Check.NotNull(request, nameof(request));
|
||||||
|
Check.NotNull(originalRequestMessage, nameof(originalRequestMessage));
|
||||||
|
Check.NotNull(originalResponseMessage, nameof(originalResponseMessage));
|
||||||
|
|
||||||
|
IBodyData bodyData;
|
||||||
|
IDictionary<string, WireMockList<string>> headers;
|
||||||
|
if (request.UseTransformer == true)
|
||||||
|
{
|
||||||
|
ITransformer responseMessageTransformer;
|
||||||
|
switch (request.TransformerType)
|
||||||
|
{
|
||||||
|
case TransformerType.Handlebars:
|
||||||
|
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
|
||||||
|
responseMessageTransformer = new Transformer(factoryHandlebars);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TransformerType.Scriban:
|
||||||
|
case TransformerType.ScribanDotLiquid:
|
||||||
|
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, request.TransformerType);
|
||||||
|
responseMessageTransformer = new Transformer(factoryDotLiquid);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
(bodyData, headers) = responseMessageTransformer.Transform(originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bodyData = request.BodyData;
|
||||||
|
headers = request.Headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create RequestMessage
|
||||||
|
var requestMessage = new RequestMessage(
|
||||||
|
new UrlDetails(request.Url),
|
||||||
|
request.Method,
|
||||||
|
ClientIp,
|
||||||
|
bodyData,
|
||||||
|
headers?.ToDictionary(x => x.Key, x => x.Value.ToArray())
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DateTime = DateTime.UtcNow
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create HttpRequestMessage
|
||||||
|
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, request.Url);
|
||||||
|
|
||||||
|
// Call the URL
|
||||||
|
return client.SendAsync(httpRequestMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
|
using WireMock.Models;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
|
||||||
@@ -93,6 +94,11 @@ namespace WireMock
|
|||||||
/// </value>
|
/// </value>
|
||||||
bool LogMapping { get; }
|
bool LogMapping { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Webhook.
|
||||||
|
/// </summary>
|
||||||
|
IWebhook Webhook { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ProvideResponseAsync
|
/// ProvideResponseAsync
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
|
using WireMock.Models;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
|
||||||
@@ -54,6 +56,9 @@ namespace WireMock
|
|||||||
/// <inheritdoc cref="IMapping.LogMapping" />
|
/// <inheritdoc cref="IMapping.LogMapping" />
|
||||||
public bool LogMapping => !(Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider);
|
public bool LogMapping => !(Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider);
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IMapping.Webhook" />
|
||||||
|
public IWebhook Webhook { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -68,6 +73,7 @@ namespace WireMock
|
|||||||
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
|
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
|
||||||
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
|
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
|
||||||
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
|
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
|
||||||
|
/// <param name="webhook">The Webhook. [Optional]</param>
|
||||||
public Mapping(
|
public Mapping(
|
||||||
Guid guid,
|
Guid guid,
|
||||||
[CanBeNull] string title,
|
[CanBeNull] string title,
|
||||||
@@ -79,7 +85,8 @@ namespace WireMock
|
|||||||
[CanBeNull] string scenario,
|
[CanBeNull] string scenario,
|
||||||
[CanBeNull] string executionConditionState,
|
[CanBeNull] string executionConditionState,
|
||||||
[CanBeNull] string nextState,
|
[CanBeNull] string nextState,
|
||||||
[CanBeNull] int? stateTimes)
|
[CanBeNull] int? stateTimes,
|
||||||
|
[CanBeNull] IWebhook webhook)
|
||||||
{
|
{
|
||||||
Guid = guid;
|
Guid = guid;
|
||||||
Title = title;
|
Title = title;
|
||||||
@@ -92,6 +99,7 @@ namespace WireMock
|
|||||||
ExecutionConditionState = executionConditionState;
|
ExecutionConditionState = executionConditionState;
|
||||||
NextState = nextState;
|
NextState = nextState;
|
||||||
StateTimes = stateTimes;
|
StateTimes = stateTimes;
|
||||||
|
Webhook = webhook;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace WireMock.Util
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// BodyData
|
/// BodyData
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BodyData : IBodyData
|
internal class BodyData : IBodyData
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="IBodyData.Encoding" />
|
/// <inheritdoc cref="IBodyData.Encoding" />
|
||||||
public Encoding Encoding { get; set; }
|
public Encoding Encoding { get; set; }
|
||||||
15
src/WireMock.Net/Models/Webhook.cs
Normal file
15
src/WireMock.Net/Models/Webhook.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
|
namespace WireMock.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Webhook
|
||||||
|
/// </summary>
|
||||||
|
public class Webhook : IWebhook
|
||||||
|
{
|
||||||
|
/// <inheritdoc cref="IWebhook.Request"/>
|
||||||
|
public IWebhookRequest Request { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
30
src/WireMock.Net/Models/WebhookRequest.cs
Normal file
30
src/WireMock.Net/Models/WebhookRequest.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
|
namespace WireMock.Models
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// WebhookRequest
|
||||||
|
/// </summary>
|
||||||
|
public class WebhookRequest : IWebhookRequest
|
||||||
|
{
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.Url"/>
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.Method"/>
|
||||||
|
public string Method { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.Headers"/>
|
||||||
|
public IDictionary<string, WireMockList<string>> Headers { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.BodyData"/>
|
||||||
|
public IBodyData BodyData { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.UseTransformer"/>
|
||||||
|
public bool? UseTransformer { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWebhookRequest.TransformerType"/>
|
||||||
|
public TransformerType TransformerType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -53,7 +53,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BodyData body = null;
|
IBodyData body = null;
|
||||||
if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true))
|
if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true))
|
||||||
{
|
{
|
||||||
var bodyParserSettings = new BodyParserSettings
|
var bodyParserSettings = new BodyParserSettings
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using WireMock.Serialization;
|
|||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Validation;
|
using WireMock.Validation;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
|
using WireMock.Settings;
|
||||||
#if !USE_ASPNETCORE
|
#if !USE_ASPNETCORE
|
||||||
using Microsoft.Owin;
|
using Microsoft.Owin;
|
||||||
using IContext = Microsoft.Owin.IOwinContext;
|
using IContext = Microsoft.Owin.IOwinContext;
|
||||||
@@ -153,6 +154,11 @@ namespace WireMock.Owin
|
|||||||
{
|
{
|
||||||
UpdateScenarioState(targetMapping);
|
UpdateScenarioState(targetMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!targetMapping.IsAdminInterface && targetMapping.Webhook != null)
|
||||||
|
{
|
||||||
|
await SendToWebhookAsync(targetMapping, request, response).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -184,6 +190,21 @@ namespace WireMock.Owin
|
|||||||
await CompletedTask;
|
await CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task SendToWebhookAsync(IMapping mapping, RequestMessage request, ResponseMessage response)
|
||||||
|
{
|
||||||
|
var httpClientForWebhook = HttpClientBuilder.Build(mapping.Settings.WebhookSettings ?? new WebhookSettings());
|
||||||
|
var webhookSender = new WebhookSender(mapping.Settings);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await webhookSender.SendAsync(httpClientForWebhook, mapping.Webhook.Request, request, response).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_options.Logger.Error($"Sending message to Webhook Mapping '{mapping.Guid}' failed. Exception: {ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateScenarioState(IMapping mapping)
|
private void UpdateScenarioState(IMapping mapping)
|
||||||
{
|
{
|
||||||
var scenario = _options.Scenarios[mapping.Scenario];
|
var scenario = _options.Scenarios[mapping.Scenario];
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using HandlebarsDotNet.Helpers.Validation;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using WireMock.Http;
|
using WireMock.Http;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
@@ -106,7 +105,7 @@ namespace WireMock.Proxy
|
|||||||
|
|
||||||
var response = Response.Create(responseMessage);
|
var response = Response.Create(responseMessage);
|
||||||
|
|
||||||
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null);
|
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ namespace WireMock
|
|||||||
/// <param name="bodyData">The BodyData.</param>
|
/// <param name="bodyData">The BodyData.</param>
|
||||||
/// <param name="headers">The headers.</param>
|
/// <param name="headers">The headers.</param>
|
||||||
/// <param name="cookies">The cookies.</param>
|
/// <param name="cookies">The cookies.</param>
|
||||||
public RequestMessage([NotNull] UrlDetails urlDetails, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] BodyData bodyData = null, [CanBeNull] IDictionary<string, string[]> headers = null, [CanBeNull] IDictionary<string, string> cookies = null)
|
public RequestMessage([NotNull] UrlDetails urlDetails, [NotNull] string method, [NotNull] string clientIP, [CanBeNull] IBodyData bodyData = null, [CanBeNull] IDictionary<string, string[]> headers = null, [CanBeNull] IDictionary<string, string> cookies = null)
|
||||||
{
|
{
|
||||||
Check.NotNull(urlDetails, nameof(urlDetails));
|
Check.NotNull(urlDetails, nameof(urlDetails));
|
||||||
Check.NotNull(method, nameof(method));
|
Check.NotNull(method, nameof(method));
|
||||||
|
|||||||
@@ -84,7 +84,8 @@ namespace WireMock.Serialization
|
|||||||
Response = new ResponseModel
|
Response = new ResponseModel
|
||||||
{
|
{
|
||||||
Delay = (int?)response.Delay?.TotalMilliseconds
|
Delay = (int?)response.Delay?.TotalMilliseconds
|
||||||
}
|
},
|
||||||
|
Webhook = WebhookMapper.Map(mapping.Webhook)
|
||||||
};
|
};
|
||||||
|
|
||||||
if (bodyMatcher?.Matchers != null)
|
if (bodyMatcher?.Matchers != null)
|
||||||
|
|||||||
103
src/WireMock.Net/Serialization/WebhookMapper.cs
Normal file
103
src/WireMock.Net/Serialization/WebhookMapper.cs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
using WireMock.Http;
|
||||||
|
using WireMock.Models;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
|
namespace WireMock.Serialization
|
||||||
|
{
|
||||||
|
internal static class WebhookMapper
|
||||||
|
{
|
||||||
|
public static IWebhook Map(WebhookModel model)
|
||||||
|
{
|
||||||
|
var webhook = new Webhook
|
||||||
|
{
|
||||||
|
Request = new WebhookRequest
|
||||||
|
{
|
||||||
|
Url = model.Request.Url,
|
||||||
|
Method = model.Request.Method,
|
||||||
|
Headers = model.Request.Headers?.ToDictionary(x => x.Key, x => new WireMockList<string>(x.Value)) ?? new Dictionary<string, WireMockList<string>>()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (model.Request.UseTransformer == true)
|
||||||
|
{
|
||||||
|
webhook.Request.UseTransformer = true;
|
||||||
|
if (!Enum.TryParse<TransformerType>(model.Request.TransformerType, out var transformerType))
|
||||||
|
{
|
||||||
|
transformerType = TransformerType.Handlebars;
|
||||||
|
}
|
||||||
|
webhook.Request.TransformerType = transformerType;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerable<string> contentTypeHeader = null;
|
||||||
|
if (webhook.Request.Headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
contentTypeHeader = webhook.Request.Headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (model.Request.Body != null)
|
||||||
|
{
|
||||||
|
webhook.Request.BodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsString = model.Request.Body,
|
||||||
|
DetectedBodyType = BodyType.String,
|
||||||
|
DetectedBodyTypeFromContentType = BodyParser.DetectBodyTypeFromContentType(contentTypeHeader?.FirstOrDefault())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (model.Request.BodyAsJson != null)
|
||||||
|
{
|
||||||
|
webhook.Request.BodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = model.Request.BodyAsJson,
|
||||||
|
DetectedBodyType = BodyType.Json,
|
||||||
|
DetectedBodyTypeFromContentType = BodyParser.DetectBodyTypeFromContentType(contentTypeHeader?.FirstOrDefault())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return webhook;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WebhookModel Map(IWebhook webhook)
|
||||||
|
{
|
||||||
|
if (webhook?.Request == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var model = new WebhookModel
|
||||||
|
{
|
||||||
|
Request = new WebhookRequestModel
|
||||||
|
{
|
||||||
|
Url = webhook.Request.Url,
|
||||||
|
Method = webhook.Request.Method,
|
||||||
|
Headers = webhook.Request.Headers?.ToDictionary(x => x.Key, x => x.Value.ToString()),
|
||||||
|
UseTransformer = webhook.Request.UseTransformer,
|
||||||
|
TransformerType = webhook.Request.UseTransformer == true ? webhook.Request.TransformerType.ToString() : null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (webhook.Request.BodyData != null)
|
||||||
|
{
|
||||||
|
switch (webhook.Request.BodyData.DetectedBodyType)
|
||||||
|
{
|
||||||
|
case BodyType.String:
|
||||||
|
model.Request.Body = webhook.Request.BodyData.BodyAsString;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BodyType.Json:
|
||||||
|
model.Request.BodyAsJson = webhook.Request.BodyData.BodyAsJson;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using WireMock.Models;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Server
|
namespace WireMock.Server
|
||||||
{
|
{
|
||||||
@@ -97,5 +101,50 @@ namespace WireMock.Server
|
|||||||
/// <param name="times">The number of times this match should be matched before the state will be changed to the specified one. Default value is 1.</param>
|
/// <param name="times">The number of times this match should be matched before the state will be changed to the specified one. Default value is 1.</param>
|
||||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
IRespondWithAProvider WillSetStateTo(int state, int? times = 1);
|
IRespondWithAProvider WillSetStateTo(int state, int? times = 1);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a Webbook to call after the response has been generated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="webhook">The Webhook</param>
|
||||||
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
|
IRespondWithAProvider WithWebhook(IWebhook webhook);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a Webbook to call after the response has been generated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The Webhook Url</param>
|
||||||
|
/// <param name="method">The method to use. [optional]</param>
|
||||||
|
/// <param name="headers">The Headers to send. [optional]</param>
|
||||||
|
/// <param name="body">The body (as string) to send. [optional]</param>
|
||||||
|
/// <param name="useTransformer">Use Transformer. [optional]</param>
|
||||||
|
/// <param name="transformerType">The transformer type. [optional]</param>
|
||||||
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
|
IRespondWithAProvider WithWebhook(
|
||||||
|
[NotNull] string url,
|
||||||
|
[CanBeNull] string method = "post",
|
||||||
|
[CanBeNull] IDictionary<string, WireMockList<string>> headers = null,
|
||||||
|
[CanBeNull] string body = null,
|
||||||
|
bool useTransformer = true,
|
||||||
|
TransformerType transformerType = TransformerType.Handlebars
|
||||||
|
);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a Webbook to call after the response has been generated.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The Webhook Url</param>
|
||||||
|
/// <param name="method">The method to use. [optional]</param>
|
||||||
|
/// <param name="headers">The Headers to send. [optional]</param>
|
||||||
|
/// <param name="body">The body (as json) to send. [optional]</param>
|
||||||
|
/// <param name="useTransformer">Use Transformer. [optional]</param>
|
||||||
|
/// <param name="transformerType">The transformer type. [optional]</param>
|
||||||
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
|
IRespondWithAProvider WithWebhook(
|
||||||
|
[NotNull] string url,
|
||||||
|
[CanBeNull] string method = "post",
|
||||||
|
[CanBeNull] IDictionary<string, WireMockList<string>> headers = null,
|
||||||
|
[CanBeNull] object body = null,
|
||||||
|
bool useTransformer = true,
|
||||||
|
TransformerType transformerType = TransformerType.Handlebars
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
||||||
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
|
using WireMock.Models;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Server
|
namespace WireMock.Server
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,6 +31,8 @@ namespace WireMock.Server
|
|||||||
|
|
||||||
public Guid Guid { get; private set; } = Guid.NewGuid();
|
public Guid Guid { get; private set; } = Guid.NewGuid();
|
||||||
|
|
||||||
|
public IWebhook Webhook { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="RespondWithAProvider"/> class.
|
/// Initializes a new instance of the <see cref="RespondWithAProvider"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -47,7 +54,7 @@ namespace WireMock.Server
|
|||||||
/// <param name="provider">The provider.</param>
|
/// <param name="provider">The provider.</param>
|
||||||
public void RespondWith(IResponseProvider provider)
|
public void RespondWith(IResponseProvider provider)
|
||||||
{
|
{
|
||||||
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState), _saveToFile);
|
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhook), _saveToFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <see cref="IRespondWithAProvider.WithGuid(string)"/>
|
/// <see cref="IRespondWithAProvider.WithGuid(string)"/>
|
||||||
@@ -140,5 +147,81 @@ namespace WireMock.Server
|
|||||||
{
|
{
|
||||||
return WillSetStateTo(state.ToString(), times);
|
return WillSetStateTo(state.ToString(), times);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <see cref="IRespondWithAProvider.WithWebhook(IWebhook)"/>
|
||||||
|
public IRespondWithAProvider WithWebhook(IWebhook webhook)
|
||||||
|
{
|
||||||
|
Webhook = webhook;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <see cref="IRespondWithAProvider.WithWebhook(string,string, IDictionary{string, WireMockList{string}}, string, bool, TransformerType)"/>
|
||||||
|
public IRespondWithAProvider WithWebhook(
|
||||||
|
[NotNull] string url,
|
||||||
|
[CanBeNull] string method = "post",
|
||||||
|
[CanBeNull] IDictionary<string, WireMockList<string>> headers = null,
|
||||||
|
[CanBeNull] string body = null,
|
||||||
|
bool useTransformer = true,
|
||||||
|
TransformerType transformerType = TransformerType.Handlebars)
|
||||||
|
{
|
||||||
|
Webhook = InitWebhook(url, method, headers, useTransformer, transformerType);
|
||||||
|
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
Webhook.Request.BodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsString = body,
|
||||||
|
DetectedBodyType = BodyType.String,
|
||||||
|
DetectedBodyTypeFromContentType = BodyType.String
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <see cref="IRespondWithAProvider.WithWebhook(string, string, IDictionary{string, WireMockList{string}}, object, bool, TransformerType)"/>
|
||||||
|
public IRespondWithAProvider WithWebhook(
|
||||||
|
[NotNull] string url,
|
||||||
|
[CanBeNull] string method = "post",
|
||||||
|
[CanBeNull] IDictionary<string, WireMockList<string>> headers = null,
|
||||||
|
[CanBeNull] object body = null,
|
||||||
|
bool useTransformer = true,
|
||||||
|
TransformerType transformerType = TransformerType.Handlebars)
|
||||||
|
{
|
||||||
|
Webhook = InitWebhook(url, method, headers, useTransformer, transformerType);
|
||||||
|
|
||||||
|
if (body != null)
|
||||||
|
{
|
||||||
|
Webhook.Request.BodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = body,
|
||||||
|
DetectedBodyType = BodyType.Json,
|
||||||
|
DetectedBodyTypeFromContentType = BodyType.Json
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IWebhook InitWebhook(
|
||||||
|
string url,
|
||||||
|
string method,
|
||||||
|
IDictionary<string, WireMockList<string>> headers,
|
||||||
|
bool useTransformer,
|
||||||
|
TransformerType transformerType)
|
||||||
|
{
|
||||||
|
return new Webhook
|
||||||
|
{
|
||||||
|
Request = new WebhookRequest
|
||||||
|
{
|
||||||
|
Url = url,
|
||||||
|
Method = method ?? "post",
|
||||||
|
Headers = headers,
|
||||||
|
UseTransformer = useTransformer,
|
||||||
|
TransformerType = transformerType
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -470,6 +470,11 @@ namespace WireMock.Server
|
|||||||
respondProvider = respondProvider.WillSetStateTo(mappingModel.SetStateTo);
|
respondProvider = respondProvider.WillSetStateTo(mappingModel.SetStateTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mappingModel.Webhook?.Request != null)
|
||||||
|
{
|
||||||
|
respondProvider = respondProvider.WithWebhook(WebhookMapper.Map(mappingModel.Webhook));
|
||||||
|
}
|
||||||
|
|
||||||
respondProvider.RespondWith(responseBuilder);
|
respondProvider.RespondWith(responseBuilder);
|
||||||
|
|
||||||
return respondProvider.Guid;
|
return respondProvider.Guid;
|
||||||
|
|||||||
17
src/WireMock.Net/Settings/HttpClientSettings.cs
Normal file
17
src/WireMock.Net/Settings/HttpClientSettings.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
namespace WireMock.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// HttpClientSettings
|
||||||
|
/// </summary>
|
||||||
|
public class HttpClientSettings : IHttpClientSettings
|
||||||
|
{
|
||||||
|
/// <inheritdoc cref="IHttpClientSettings.ClientX509Certificate2ThumbprintOrSubjectName"/>
|
||||||
|
public string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IHttpClientSettings.WebProxySettings"/>
|
||||||
|
public IWebProxySettings WebProxySettings { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IHttpClientSettings.AllowAutoRedirect"/>
|
||||||
|
public bool? AllowAutoRedirect { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/WireMock.Net/Settings/IHttpClientSettings.cs
Normal file
24
src/WireMock.Net/Settings/IHttpClientSettings.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
namespace WireMock.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IHttpClientSettings
|
||||||
|
/// </summary>
|
||||||
|
public interface IHttpClientSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The clientCertificate thumbprint or subject name fragment to use.
|
||||||
|
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
|
||||||
|
/// </summary>
|
||||||
|
string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the WebProxySettings.
|
||||||
|
/// </summary>
|
||||||
|
IWebProxySettings WebProxySettings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Proxy requests should follow redirection (30x).
|
||||||
|
/// </summary>
|
||||||
|
bool? AllowAutoRedirect { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace WireMock.Settings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// IProxyAndRecordSettings
|
/// IProxyAndRecordSettings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IProxyAndRecordSettings
|
public interface IProxyAndRecordSettings : IHttpClientSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The URL to proxy.
|
/// The URL to proxy.
|
||||||
@@ -29,12 +29,6 @@ namespace WireMock.Settings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
bool SaveMappingToFile { get; set; }
|
bool SaveMappingToFile { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The clientCertificate thumbprint or subject name fragment to use.
|
|
||||||
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
|
|
||||||
/// </summary>
|
|
||||||
string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a list from headers which will be excluded from the saved mappings.
|
/// Defines a list from headers which will be excluded from the saved mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,15 +38,5 @@ namespace WireMock.Settings
|
|||||||
/// Defines a list of cookies which will be excluded from the saved mappings.
|
/// Defines a list of cookies which will be excluded from the saved mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string[] ExcludedCookies { get; set; }
|
string[] ExcludedCookies { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines the WebProxySettings.
|
|
||||||
/// </summary>
|
|
||||||
IWebProxySettings WebProxySettings { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Proxy requests should follow redirection (30x).
|
|
||||||
/// </summary>
|
|
||||||
bool? AllowAutoRedirect { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
9
src/WireMock.Net/Settings/IWebhookSettings.cs
Normal file
9
src/WireMock.Net/Settings/IWebhookSettings.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace WireMock.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// IWebhookSettings
|
||||||
|
/// </summary>
|
||||||
|
public interface IWebhookSettings : IHttpClientSettings
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -186,5 +186,11 @@ namespace WireMock.Settings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
bool CustomCertificateDefined { get; }
|
bool CustomCertificateDefined { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the global IWebhookSettingsto use
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
IWebhookSettings WebhookSettings { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace WireMock.Settings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// ProxyAndRecordSettings
|
/// ProxyAndRecordSettings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ProxyAndRecordSettings : IProxyAndRecordSettings
|
public class ProxyAndRecordSettings : HttpClientSettings, IProxyAndRecordSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The URL to proxy.
|
/// The URL to proxy.
|
||||||
@@ -32,13 +32,6 @@ namespace WireMock.Settings
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string SaveMappingForStatusCodePattern { get; set; } = "*";
|
public string SaveMappingForStatusCodePattern { get; set; } = "*";
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The clientCertificate thumbprint or subject name fragment to use.
|
|
||||||
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
|
|
||||||
/// </summary>
|
|
||||||
[PublicAPI]
|
|
||||||
public string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IProxyAndRecordSettings.ExcludedHeaders"/>
|
/// <inheritdoc cref="IProxyAndRecordSettings.ExcludedHeaders"/>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string[] ExcludedHeaders { get; set; }
|
public string[] ExcludedHeaders { get; set; }
|
||||||
@@ -46,13 +39,5 @@ namespace WireMock.Settings
|
|||||||
/// <inheritdoc cref="IProxyAndRecordSettings.ExcludedCookies"/>
|
/// <inheritdoc cref="IProxyAndRecordSettings.ExcludedCookies"/>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string[] ExcludedCookies { get; set; }
|
public string[] ExcludedCookies { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IProxyAndRecordSettings.WebProxySettings"/>
|
|
||||||
[PublicAPI]
|
|
||||||
public IWebProxySettings WebProxySettings { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IProxyAndRecordSettings.AllowAutoRedirect"/>
|
|
||||||
[PublicAPI]
|
|
||||||
public bool? AllowAutoRedirect { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
9
src/WireMock.Net/Settings/WebhookSettings.cs
Normal file
9
src/WireMock.Net/Settings/WebhookSettings.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
namespace WireMock.Settings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// WebhookSettings
|
||||||
|
/// </summary>
|
||||||
|
public class WebhookSettings : HttpClientSettings, IWebhookSettings
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -129,5 +129,9 @@ namespace WireMock.Settings
|
|||||||
/// <inheritdoc cref="IWireMockServerSettings.CustomCertificateDefined"/>
|
/// <inheritdoc cref="IWireMockServerSettings.CustomCertificateDefined"/>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
|
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWireMockServerSettings.WebhookSettings"/>
|
||||||
|
[PublicAPI]
|
||||||
|
public IWebhookSettings WebhookSettings { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,13 @@
|
|||||||
namespace WireMock.Transformers
|
using System.Collections.Generic;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
|
namespace WireMock.Transformers
|
||||||
{
|
{
|
||||||
interface ITransformer
|
interface ITransformer
|
||||||
{
|
{
|
||||||
ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile);
|
ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile);
|
||||||
|
|
||||||
|
(IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,227 +1,265 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using WireMock.Validation;
|
|
||||||
|
namespace WireMock.Transformers.Handlebars
|
||||||
namespace WireMock.Transformers.Handlebars
|
{
|
||||||
{
|
internal class Transformer : ITransformer
|
||||||
internal class Transformer : ITransformer
|
{
|
||||||
{
|
private readonly ITransformerContextFactory _factory;
|
||||||
private readonly ITransformerContextFactory _factory;
|
|
||||||
|
public Transformer([NotNull] ITransformerContextFactory factory)
|
||||||
public Transformer([NotNull] ITransformerContextFactory factory)
|
{
|
||||||
{
|
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
|
||||||
Check.NotNull(factory, nameof(factory));
|
}
|
||||||
|
|
||||||
_factory = factory;
|
public (IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers)
|
||||||
}
|
{
|
||||||
|
var transformerContext = _factory.Create();
|
||||||
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile)
|
|
||||||
{
|
var model = new
|
||||||
var handlebarsContext = _factory.Create();
|
{
|
||||||
|
request = originalRequestMessage,
|
||||||
var responseMessage = new ResponseMessage();
|
response = originalResponseMessage
|
||||||
|
};
|
||||||
var model = new { request = requestMessage };
|
|
||||||
|
IBodyData newBodyData = null;
|
||||||
switch (original.BodyData?.DetectedBodyType)
|
if (bodyData?.DetectedBodyType != null)
|
||||||
{
|
{
|
||||||
case BodyType.Json:
|
newBodyData = TransformBodyData(transformerContext, model, bodyData, false);
|
||||||
TransformBodyAsJson(handlebarsContext, model, original, responseMessage);
|
}
|
||||||
break;
|
|
||||||
|
return (newBodyData, TransformHeaders(transformerContext, model, headers));
|
||||||
case BodyType.File:
|
}
|
||||||
TransformBodyAsFile(handlebarsContext, model, original, responseMessage, useTransformerForBodyAsFile);
|
|
||||||
break;
|
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile)
|
||||||
|
{
|
||||||
case BodyType.String:
|
var transformerContext = _factory.Create();
|
||||||
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
|
||||||
TransformBodyAsString(handlebarsContext, model, original, responseMessage);
|
var responseMessage = new ResponseMessage();
|
||||||
break;
|
|
||||||
}
|
var model = new
|
||||||
|
{
|
||||||
responseMessage.FaultType = original.FaultType;
|
request = requestMessage
|
||||||
responseMessage.FaultPercentage = original.FaultPercentage;
|
};
|
||||||
|
|
||||||
// Headers
|
if (original.BodyData?.DetectedBodyType != null)
|
||||||
var newHeaders = new Dictionary<string, WireMockList<string>>();
|
{
|
||||||
foreach (var header in original.Headers)
|
responseMessage.BodyData = TransformBodyData(transformerContext, model, original.BodyData, useTransformerForBodyAsFile);
|
||||||
{
|
|
||||||
var headerKey = handlebarsContext.ParseAndRender(header.Key, model);
|
if (original.BodyData.DetectedBodyType == BodyType.String)
|
||||||
var templateHeaderValues = header.Value
|
{
|
||||||
.Select(text => handlebarsContext.ParseAndRender(text, model))
|
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
||||||
.ToArray();
|
}
|
||||||
|
}
|
||||||
newHeaders.Add(headerKey, new WireMockList<string>(templateHeaderValues));
|
|
||||||
}
|
responseMessage.FaultType = original.FaultType;
|
||||||
|
responseMessage.FaultPercentage = original.FaultPercentage;
|
||||||
responseMessage.Headers = newHeaders;
|
|
||||||
|
responseMessage.Headers = TransformHeaders(transformerContext, model, original.Headers);
|
||||||
switch (original.StatusCode)
|
|
||||||
{
|
switch (original.StatusCode)
|
||||||
case int statusCodeAsInteger:
|
{
|
||||||
responseMessage.StatusCode = statusCodeAsInteger;
|
case int statusCodeAsInteger:
|
||||||
break;
|
responseMessage.StatusCode = statusCodeAsInteger;
|
||||||
|
break;
|
||||||
case string statusCodeAsString:
|
|
||||||
responseMessage.StatusCode = handlebarsContext.ParseAndRender(statusCodeAsString, model);
|
case string statusCodeAsString:
|
||||||
break;
|
responseMessage.StatusCode = transformerContext.ParseAndRender(statusCodeAsString, model);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
return responseMessage;
|
|
||||||
}
|
return responseMessage;
|
||||||
|
}
|
||||||
private static void TransformBodyAsJson(ITransformerContext handlebarsContext, object model, ResponseMessage original, ResponseMessage responseMessage)
|
|
||||||
{
|
private static IBodyData TransformBodyData(ITransformerContext transformerContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||||
JToken jToken;
|
{
|
||||||
switch (original.BodyData.BodyAsJson)
|
switch (original?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case JObject bodyAsJObject:
|
case BodyType.Json:
|
||||||
jToken = bodyAsJObject.DeepClone();
|
return TransformBodyAsJson(transformerContext, model, original);
|
||||||
WalkNode(handlebarsContext, jToken, model);
|
|
||||||
break;
|
case BodyType.File:
|
||||||
|
return TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile);
|
||||||
case Array bodyAsArray:
|
|
||||||
jToken = JArray.FromObject(bodyAsArray);
|
case BodyType.String:
|
||||||
WalkNode(handlebarsContext, jToken, model);
|
return TransformBodyAsString(transformerContext, model, original);
|
||||||
break;
|
|
||||||
|
default:
|
||||||
case string bodyAsString:
|
return null;
|
||||||
jToken = ReplaceSingleNode(handlebarsContext, bodyAsString, model);
|
}
|
||||||
break;
|
}
|
||||||
|
|
||||||
default:
|
private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, object model, IDictionary<string, WireMockList<string>> original)
|
||||||
jToken = JObject.FromObject(original.BodyData.BodyAsJson);
|
{
|
||||||
WalkNode(handlebarsContext, jToken, model);
|
if (original == null)
|
||||||
break;
|
{
|
||||||
}
|
return new Dictionary<string, WireMockList<string>>();
|
||||||
|
}
|
||||||
responseMessage.BodyData = new BodyData
|
|
||||||
{
|
var newHeaders = new Dictionary<string, WireMockList<string>>();
|
||||||
Encoding = original.BodyData.Encoding,
|
foreach (var header in original)
|
||||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
{
|
||||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
var headerKey = transformerContext.ParseAndRender(header.Key, model);
|
||||||
BodyAsJson = jToken
|
var templateHeaderValues = header.Value.Select(text => transformerContext.ParseAndRender(text, model)).ToArray();
|
||||||
};
|
|
||||||
}
|
newHeaders.Add(headerKey, new WireMockList<string>(templateHeaderValues));
|
||||||
|
}
|
||||||
private static JToken ReplaceSingleNode(ITransformerContext handlebarsContext, string stringValue, object model)
|
|
||||||
{
|
return newHeaders;
|
||||||
string transformedString = handlebarsContext.ParseAndRender(stringValue, model) as string;
|
}
|
||||||
|
|
||||||
if (!string.Equals(stringValue, transformedString))
|
private static IBodyData TransformBodyAsJson(ITransformerContext handlebarsContext, object model, IBodyData original)
|
||||||
{
|
{
|
||||||
const string property = "_";
|
JToken jToken;
|
||||||
JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
|
switch (original.BodyAsJson)
|
||||||
JToken node = dummy[property];
|
{
|
||||||
|
case JObject bodyAsJObject:
|
||||||
ReplaceNodeValue(node, transformedString);
|
jToken = bodyAsJObject.DeepClone();
|
||||||
|
WalkNode(handlebarsContext, jToken, model);
|
||||||
return dummy[property];
|
break;
|
||||||
}
|
|
||||||
|
case Array bodyAsArray:
|
||||||
return stringValue;
|
jToken = JArray.FromObject(bodyAsArray);
|
||||||
}
|
WalkNode(handlebarsContext, jToken, model);
|
||||||
|
break;
|
||||||
private static void WalkNode(ITransformerContext handlebarsContext, JToken node, object model)
|
|
||||||
{
|
case string bodyAsString:
|
||||||
if (node.Type == JTokenType.Object)
|
jToken = ReplaceSingleNode(handlebarsContext, bodyAsString, model);
|
||||||
{
|
break;
|
||||||
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
|
||||||
foreach (JProperty child in node.Children<JProperty>().ToArray())
|
default:
|
||||||
{
|
jToken = JObject.FromObject(original.BodyAsJson);
|
||||||
WalkNode(handlebarsContext, child.Value, model);
|
WalkNode(handlebarsContext, jToken, model);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
else if (node.Type == JTokenType.Array)
|
|
||||||
{
|
return new BodyData
|
||||||
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
{
|
||||||
foreach (JToken child in node.Children().ToArray())
|
Encoding = original.Encoding,
|
||||||
{
|
DetectedBodyType = original.DetectedBodyType,
|
||||||
WalkNode(handlebarsContext, child, model);
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
}
|
BodyAsJson = jToken
|
||||||
}
|
};
|
||||||
else if (node.Type == JTokenType.String)
|
}
|
||||||
{
|
|
||||||
// In case of string, try to transform the value.
|
private static JToken ReplaceSingleNode(ITransformerContext handlebarsContext, string stringValue, object model)
|
||||||
string stringValue = node.Value<string>();
|
{
|
||||||
if (string.IsNullOrEmpty(stringValue))
|
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
||||||
{
|
|
||||||
return;
|
if (!string.Equals(stringValue, transformedString))
|
||||||
}
|
{
|
||||||
|
const string property = "_";
|
||||||
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
|
||||||
if (!string.Equals(stringValue, transformedString))
|
JToken node = dummy[property];
|
||||||
{
|
|
||||||
ReplaceNodeValue(node, transformedString);
|
ReplaceNodeValue(node, transformedString);
|
||||||
}
|
|
||||||
}
|
return dummy[property];
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void ReplaceNodeValue(JToken node, string stringValue)
|
return stringValue;
|
||||||
{
|
}
|
||||||
if (bool.TryParse(stringValue, out bool valueAsBoolean))
|
|
||||||
{
|
private static void WalkNode(ITransformerContext handlebarsContext, JToken node, object model)
|
||||||
node.Replace(valueAsBoolean);
|
{
|
||||||
return;
|
if (node.Type == JTokenType.Object)
|
||||||
}
|
{
|
||||||
|
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||||
JToken value;
|
foreach (JProperty child in node.Children<JProperty>().ToArray())
|
||||||
try
|
{
|
||||||
{
|
WalkNode(handlebarsContext, child.Value, model);
|
||||||
// Try to convert this string into a JsonObject
|
}
|
||||||
value = JToken.Parse(stringValue);
|
}
|
||||||
}
|
else if (node.Type == JTokenType.Array)
|
||||||
catch (JsonException)
|
{
|
||||||
{
|
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||||
// Ignore JsonException and just keep string value and convert to JToken
|
foreach (JToken child in node.Children().ToArray())
|
||||||
value = stringValue;
|
{
|
||||||
}
|
WalkNode(handlebarsContext, child, model);
|
||||||
|
}
|
||||||
node.Replace(value);
|
}
|
||||||
}
|
else if (node.Type == JTokenType.String)
|
||||||
|
{
|
||||||
private static void TransformBodyAsString(ITransformerContext handlebarsContext, object model, ResponseMessage original, ResponseMessage responseMessage)
|
// In case of string, try to transform the value.
|
||||||
{
|
string stringValue = node.Value<string>();
|
||||||
responseMessage.BodyData = new BodyData
|
if (string.IsNullOrEmpty(stringValue))
|
||||||
{
|
{
|
||||||
Encoding = original.BodyData.Encoding,
|
return;
|
||||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
}
|
||||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
|
||||||
BodyAsString = handlebarsContext.ParseAndRender(original.BodyData.BodyAsString, model)
|
string transformedString = handlebarsContext.ParseAndRender(stringValue, model);
|
||||||
};
|
if (!string.Equals(stringValue, transformedString))
|
||||||
}
|
{
|
||||||
|
ReplaceNodeValue(node, transformedString);
|
||||||
private void TransformBodyAsFile(ITransformerContext handlebarsContext, object model, ResponseMessage original, ResponseMessage responseMessage, bool useTransformerForBodyAsFile)
|
}
|
||||||
{
|
}
|
||||||
string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyData.BodyAsFile, model);
|
}
|
||||||
|
|
||||||
if (!useTransformerForBodyAsFile)
|
private static void ReplaceNodeValue(JToken node, string stringValue)
|
||||||
{
|
{
|
||||||
responseMessage.BodyData = new BodyData
|
if (bool.TryParse(stringValue, out bool valueAsBoolean))
|
||||||
{
|
{
|
||||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
node.Replace(valueAsBoolean);
|
||||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
return;
|
||||||
BodyAsFile = transformedBodyAsFilename
|
}
|
||||||
};
|
|
||||||
}
|
JToken value;
|
||||||
else
|
try
|
||||||
{
|
{
|
||||||
string text = handlebarsContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
// Try to convert this string into a JsonObject
|
||||||
|
value = JToken.Parse(stringValue);
|
||||||
responseMessage.BodyData = new BodyData
|
}
|
||||||
{
|
catch (JsonException)
|
||||||
DetectedBodyType = BodyType.String,
|
{
|
||||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
// Ignore JsonException and just keep string value and convert to JToken
|
||||||
BodyAsString = handlebarsContext.ParseAndRender(text, model),
|
value = stringValue;
|
||||||
BodyAsFile = transformedBodyAsFilename
|
}
|
||||||
};
|
|
||||||
}
|
node.Replace(value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private static IBodyData TransformBodyAsString(ITransformerContext handlebarsContext, object model, IBodyData original)
|
||||||
|
{
|
||||||
|
return new BodyData
|
||||||
|
{
|
||||||
|
Encoding = original.Encoding,
|
||||||
|
DetectedBodyType = original.DetectedBodyType,
|
||||||
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
|
BodyAsString = handlebarsContext.ParseAndRender(original.BodyAsString, model)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IBodyData TransformBodyAsFile(ITransformerContext handlebarsContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||||
|
{
|
||||||
|
string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyAsFile, model);
|
||||||
|
|
||||||
|
if (!useTransformerForBodyAsFile)
|
||||||
|
{
|
||||||
|
return new BodyData
|
||||||
|
{
|
||||||
|
DetectedBodyType = original.DetectedBodyType,
|
||||||
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
|
BodyAsFile = transformedBodyAsFilename
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string text = handlebarsContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
||||||
|
|
||||||
|
return new BodyData
|
||||||
|
{
|
||||||
|
DetectedBodyType = BodyType.String,
|
||||||
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
|
BodyAsString = handlebarsContext.ParseAndRender(text, model),
|
||||||
|
BodyAsFile = transformedBodyAsFilename
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using WireMock.Models;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Serialization;
|
using WireMock.Serialization;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace WireMock.Net.Tests.Serialization
|
namespace WireMock.Net.Tests.Serialization
|
||||||
@@ -25,7 +29,26 @@ namespace WireMock.Net.Tests.Serialization
|
|||||||
// Assign
|
// Assign
|
||||||
var request = Request.Create();
|
var request = Request.Create();
|
||||||
var response = Response.Create();
|
var response = Response.Create();
|
||||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 0, null, null, null, null);
|
var webhook = new Webhook
|
||||||
|
{
|
||||||
|
Request = new WebhookRequest
|
||||||
|
{
|
||||||
|
Url = "https://test.com",
|
||||||
|
Headers = new Dictionary<string, WireMockList<string>>
|
||||||
|
{
|
||||||
|
{ "Single", new WireMockList<string>("x") },
|
||||||
|
{ "Multi", new WireMockList<string>("a", "b") }
|
||||||
|
},
|
||||||
|
Method = "post",
|
||||||
|
BodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsString = "b",
|
||||||
|
DetectedBodyType = BodyType.String,
|
||||||
|
DetectedBodyTypeFromContentType = BodyType.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 0, null, null, null, null, webhook);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = _sut.ToMappingModel(mapping);
|
var model = _sut.ToMappingModel(mapping);
|
||||||
@@ -33,9 +56,16 @@ namespace WireMock.Net.Tests.Serialization
|
|||||||
// Assert
|
// Assert
|
||||||
model.Should().NotBeNull();
|
model.Should().NotBeNull();
|
||||||
model.Priority.Should().BeNull();
|
model.Priority.Should().BeNull();
|
||||||
|
|
||||||
model.Response.BodyAsJsonIndented.Should().BeNull();
|
model.Response.BodyAsJsonIndented.Should().BeNull();
|
||||||
model.Response.UseTransformer.Should().BeNull();
|
model.Response.UseTransformer.Should().BeNull();
|
||||||
model.Response.Headers.Should().BeNull();
|
model.Response.Headers.Should().BeNull();
|
||||||
|
|
||||||
|
model.Webhook.Request.Method.Should().Be("post");
|
||||||
|
model.Webhook.Request.Url.Should().Be("https://test.com");
|
||||||
|
model.Webhook.Request.Headers.Should().HaveCount(2);
|
||||||
|
model.Webhook.Request.Body.Should().Be("b");
|
||||||
|
model.Webhook.Request.BodyAsJson.Should().BeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -44,7 +74,7 @@ namespace WireMock.Net.Tests.Serialization
|
|||||||
// Assign
|
// Assign
|
||||||
var request = Request.Create();
|
var request = Request.Create();
|
||||||
var response = Response.Create().WithBodyAsJson(new { x = "x" }).WithTransformer();
|
var response = Response.Create().WithBodyAsJson(new { x = "x" }).WithTransformer();
|
||||||
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null);
|
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var model = _sut.ToMappingModel(mapping);
|
var model = _sut.ToMappingModel(mapping);
|
||||||
|
|||||||
101
test/WireMock.Net.Tests/Serialization/WebhookMapperTests.cs
Normal file
101
test/WireMock.Net.Tests/Serialization/WebhookMapperTests.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using FluentAssertions;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
using WireMock.Serialization;
|
||||||
|
using WireMock.Types;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests.Serialization
|
||||||
|
{
|
||||||
|
public class WebhookMapperTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void WebhookMapper_Map_Model_BodyAsString_And_UseTransformerIsFalse()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var model = new WebhookModel
|
||||||
|
{
|
||||||
|
Request = new WebhookRequestModel
|
||||||
|
{
|
||||||
|
Url = "https://localhost",
|
||||||
|
Method = "get",
|
||||||
|
Headers = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "x", "y" }
|
||||||
|
},
|
||||||
|
Body = "test",
|
||||||
|
UseTransformer = false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = WebhookMapper.Map(model);
|
||||||
|
|
||||||
|
result.Request.Url.Should().Be("https://localhost");
|
||||||
|
result.Request.Method.Should().Be("get");
|
||||||
|
result.Request.Headers.Should().HaveCount(1);
|
||||||
|
result.Request.BodyData.BodyAsJson.Should().BeNull();
|
||||||
|
result.Request.BodyData.BodyAsString.Should().Be("test");
|
||||||
|
result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.String);
|
||||||
|
result.Request.UseTransformer.Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WebhookMapper_Map_Model_BodyAsString_And_UseTransformerIsTrue()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var model = new WebhookModel
|
||||||
|
{
|
||||||
|
Request = new WebhookRequestModel
|
||||||
|
{
|
||||||
|
Url = "https://localhost",
|
||||||
|
Method = "get",
|
||||||
|
Headers = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "x", "y" }
|
||||||
|
},
|
||||||
|
Body = "test",
|
||||||
|
UseTransformer = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = WebhookMapper.Map(model);
|
||||||
|
|
||||||
|
result.Request.Url.Should().Be("https://localhost");
|
||||||
|
result.Request.Method.Should().Be("get");
|
||||||
|
result.Request.Headers.Should().HaveCount(1);
|
||||||
|
result.Request.BodyData.BodyAsJson.Should().BeNull();
|
||||||
|
result.Request.BodyData.BodyAsString.Should().Be("test");
|
||||||
|
result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.String);
|
||||||
|
result.Request.UseTransformer.Should().BeTrue();
|
||||||
|
result.Request.TransformerType.Should().Be(TransformerType.Handlebars);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WebhookMapper_Map_Model_BodyAsJson()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var model = new WebhookModel
|
||||||
|
{
|
||||||
|
Request = new WebhookRequestModel
|
||||||
|
{
|
||||||
|
Url = "https://localhost",
|
||||||
|
Method = "get",
|
||||||
|
Headers = new Dictionary<string, string>
|
||||||
|
{
|
||||||
|
{ "x", "y" }
|
||||||
|
},
|
||||||
|
BodyAsJson = new { n = 12345 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var result = WebhookMapper.Map(model);
|
||||||
|
|
||||||
|
result.Request.Url.Should().Be("https://localhost");
|
||||||
|
result.Request.Method.Should().Be("get");
|
||||||
|
result.Request.Headers.Should().HaveCount(1);
|
||||||
|
result.Request.BodyData.BodyAsString.Should().BeNull();
|
||||||
|
result.Request.BodyData.BodyAsJson.Should().NotBeNull();
|
||||||
|
result.Request.BodyData.DetectedBodyType.Should().Be(BodyType.Json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
test/WireMock.Net.Tests/WireMockServer.WebhookTests.cs
Normal file
133
test/WireMock.Net.Tests/WireMockServer.WebhookTests.cs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using WireMock.Models;
|
||||||
|
using WireMock.RequestBuilders;
|
||||||
|
using WireMock.ResponseBuilders;
|
||||||
|
using WireMock.Server;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests
|
||||||
|
{
|
||||||
|
public class WireMockServerWebhookTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task WireMockServer_WithWebhook_Should_Send_Message_To_Webhook()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var serverReceivingTheWebhook = WireMockServer.Start();
|
||||||
|
serverReceivingTheWebhook.Given(Request.Create().UsingPost()).RespondWith(Response.Create().WithStatusCode(200));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var server = WireMockServer.Start();
|
||||||
|
server.Given(Request.Create().UsingPost())
|
||||||
|
.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
|
||||||
|
{
|
||||||
|
Method = HttpMethod.Post,
|
||||||
|
RequestUri = new Uri($"{server.Urls[0]}/TST"),
|
||||||
|
Content = new StringContent("test")
|
||||||
|
};
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var response = await new HttpClient().SendAsync(request);
|
||||||
|
string content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
content.Should().Be("a-response");
|
||||||
|
|
||||||
|
serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
|
||||||
|
|
||||||
|
server.Dispose();
|
||||||
|
serverReceivingTheWebhook.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[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));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
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"));
|
||||||
|
|
||||||
|
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);
|
||||||
|
string content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
content.Should().Be("a-response");
|
||||||
|
|
||||||
|
serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
|
||||||
|
serverReceivingTheWebhook.LogEntries.First().RequestMessage.Body.Should().Be("OK !");
|
||||||
|
|
||||||
|
server.Dispose();
|
||||||
|
serverReceivingTheWebhook.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
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));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
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"));
|
||||||
|
|
||||||
|
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);
|
||||||
|
string content = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
content.Should().Be("a-response");
|
||||||
|
|
||||||
|
serverReceivingTheWebhook.LogEntries.Should().HaveCount(1);
|
||||||
|
serverReceivingTheWebhook.LogEntries.First().RequestMessage.Body.Should().Be("{\"Status\":\"OK\"}");
|
||||||
|
|
||||||
|
server.Dispose();
|
||||||
|
serverReceivingTheWebhook.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user