Compare commits

...

8 Commits

Author SHA1 Message Date
Stef Heyenrath
68ad015dcf 1.5.43 2023-12-11 17:34:39 +01:00
sameena syed
97d26338e6 Proxy all requests - even a repeated one (#1038)
* Adding proxyall

* Adding proxyAll flag

* Reverting extra spaces added

* Make proxyall to true

* Resolving review comments for proxyall

* Resolving codefactor spaces in the code

* Adding proxyall parser in wmserversettingsparser

---------

Co-authored-by: Sameena Syed <sameena.syed@nexigroup.com>
2023-12-11 17:16:30 +01:00
Stef Heyenrath
0c6129e86b Add ProxyUrlReplaceSettings to Response (#1026) 2023-12-10 09:57:37 +01:00
Stef Heyenrath
61c8ce76eb 1.5.42 2023-12-09 09:24:27 +01:00
Stef Heyenrath
8e1b6f87f0 Workaround for: Random.Generate Type="Long" (#1034)
* Workaround for: Random.Generate Type="Long"

* x

* 11

* .

* 2
2023-12-09 09:18:16 +01:00
Stef Heyenrath
c6c7ba13b4 Calling Reset also resets the scenarios (#1031)
* Calling Reset also resets the scenarios

* .
2023-12-07 16:03:37 +01:00
Stef Heyenrath
1174acce6e ResponseWithHandlebarsDateTimeTests (#1029) 2023-12-06 20:20:45 +01:00
Stef Heyenrath
932dde07e4 FixMapping[] for WireMock.Org REST API (#1023) 2023-12-06 09:24:58 +01:00
33 changed files with 685 additions and 410 deletions

View File

@@ -1,3 +1,17 @@
# 1.5.43 (11 December 2023)
- [#1026](https://github.com/WireMock-Net/WireMock.Net/pull/1026) - Add ProxyUrlReplaceSettings to Response [feature] contributed by [StefH](https://github.com/StefH)
- [#1038](https://github.com/WireMock-Net/WireMock.Net/pull/1038) - Proxy all requests - even a repeated one [feature] contributed by [sameena-ops](https://github.com/sameena-ops)
- [#592](https://github.com/WireMock-Net/WireMock.Net/issues/592) - Proxy all requests - even a repeated one [feature]
- [#1024](https://github.com/WireMock-Net/WireMock.Net/issues/1024) - Scenario with proxy not removing route prefix [feature]
# 1.5.42 (09 December 2023)
- [#1023](https://github.com/WireMock-Net/WireMock.Net/pull/1023) - Fix Mapping[] for WireMock.Org REST API [bug] contributed by [StefH](https://github.com/StefH)
- [#1029](https://github.com/WireMock-Net/WireMock.Net/pull/1029) - Add ResponseWithHandlebarsDateTimeTests [test] contributed by [StefH](https://github.com/StefH)
- [#1031](https://github.com/WireMock-Net/WireMock.Net/pull/1031) - Calling Reset also resets the scenarios [bug] contributed by [StefH](https://github.com/StefH)
- [#1034](https://github.com/WireMock-Net/WireMock.Net/pull/1034) - Workaround for: Random.Generate Type=&quot;Long&quot; [bug] contributed by [StefH](https://github.com/StefH)
- [#1021](https://github.com/WireMock-Net/WireMock.Net/issues/1021) - GetAdminMappingsResult in WireMock.Org.Abstractions should contain list of mappings [bug]
- [#1030](https://github.com/WireMock-Net/WireMock.Net/issues/1030) - Reset resets only mappings and logentries, not scenarios. [bug]
# 1.5.41 (04 December 2023)
- [#1012](https://github.com/WireMock-Net/WireMock.Net/pull/1012) - GraphQL - custom scalar support [feature] contributed by [StefH](https://github.com/StefH)
- [#1018](https://github.com/WireMock-Net/WireMock.Net/pull/1018) - Add .NET 8 [feature] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.5.41</VersionPrefix>
<VersionPrefix>1.5.43</VersionPrefix>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>

View File

@@ -1,6 +1,6 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=1.5.41
SET version=1.5.43
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%

View File

@@ -1,7 +1,7 @@
# 1.5.41 (04 December 2023)
- #1012 GraphQL - custom scalar support [feature]
- #1018 Add .NET 8 [feature]
- #1020 Add Github Action [test]
- #984 GraphQL Schema validation with custom scalars [feature]
# 1.5.43 (11 December 2023)
- #1026 Add ProxyUrlReplaceSettings to Response [feature]
- #1038 Proxy all requests - even a repeated one [feature]
- #592 Proxy all requests - even a repeated one [feature]
- #1024 Scenario with proxy not removing route prefix [feature]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -325,6 +325,23 @@ namespace WireMock.Net.ConsoleApplication
.WithHeader("Keep-Alive-Test", "stef")
);
server
.Given(Request.Create()
.UsingGet()
.WithPath("/proxy-replace")
)
.RespondWith(Response.Create()
.WithProxy(new ProxyAndRecordSettings
{
Url = "http://localhost:9999",
ReplaceSettings = new ProxyUrlReplaceSettings
{
OldValue = "old",
NewValue = "new"
}
})
);
server
.Given(Request.Create()
.WithPath("/xpath").UsingPost()

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using WireMock.Admin.Settings;
namespace WireMock.Admin.Mappings;
@@ -103,6 +104,11 @@ public class ResponseModel
/// </summary>
public string? ProxyUrl { get; set; }
/// <summary>
/// Defines the Proxy Url Replace Settings.
/// </summary>
public ProxyUrlReplaceSettingsModel? ProxyUrlReplaceSettings { get; set; }
/// <summary>
/// The client X509Certificate2 Thumbprint or SubjectName to use.
/// </summary>

View File

@@ -70,7 +70,12 @@ public class ProxyAndRecordSettingsModel
public bool AppendGuidToSavedMappingFile { get; set; }
/// <summary>
/// Defines the Replace Settings
/// Defines the Replace Settings.
/// </summary>
public ProxyUrlReplaceSettingsModel? ReplaceSettings { get; set; }
/// <summary>
/// Proxy all Api calls, irrespective of any condition
/// </summary>
public bool ProxyAll { get; set; } = false;
}

View File

@@ -1,24 +1,23 @@
namespace WireMock.Admin.Settings
namespace WireMock.Admin.Settings;
/// <summary>
/// WebProxySettings
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebProxySettingsModel
{
/// <summary>
/// WebProxySettings
/// A string instance that contains the address of the proxy server.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebProxySettingsModel
{
/// <summary>
/// A string instance that contains the address of the proxy server.
/// </summary>
public string Address { get; set; }
public string Address { get; set; } = null!;
/// <summary>
/// The user name associated with the credentials.
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// The user name associated with the credentials.
/// </summary>
public string? UserName { get; set; }
/// <summary>
/// The password for the user name associated with the credentials.
/// </summary>
public string? Password { get; set; }
}
/// <summary>
/// The password for the user name associated with the credentials.
/// </summary>
public string? Password { get; set; }
}

View File

@@ -134,7 +134,7 @@ public interface IWireMockServer : IDisposable
void RemoveAuthentication();
/// <summary>
/// Resets LogEntries and Mappings.
/// Resets LogEntries, Mappings and Scenarios.
/// </summary>
void Reset();

View File

@@ -77,4 +77,6 @@ internal interface IWireMockMiddlewareOptions
bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
public bool ProxyAll { get; set; }
}

View File

@@ -95,4 +95,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
/// <inheritdoc />
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
/// <inheritdoc />
public bool ProxyAll { get; set; }
}

View File

@@ -373,9 +373,11 @@ internal class MappingConverter
mappingModel.Response.UseTransformerForBodyAsFile = null;
mappingModel.Response.TransformerReplaceNodeOptions = null;
mappingModel.Response.BodyEncoding = null;
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
mappingModel.Response.Fault = null;
mappingModel.Response.WebProxy = MapWebProxy(response.ProxyAndRecordSettings.WebProxySettings);
mappingModel.Response.WebProxy = TinyMapperUtils.Instance.Map(response.ProxyAndRecordSettings.WebProxySettings);
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
mappingModel.Response.ProxyUrlReplaceSettings = TinyMapperUtils.Instance.Map(response.ProxyAndRecordSettings.ReplaceSettings);
}
else
{
@@ -509,16 +511,6 @@ internal class MappingConverter
return values is { } ? string.Join(", ", values.Select(ToCSharpStringLiteral)) : ToCSharpStringLiteral(defaultValue);
}
private static WebProxyModel? MapWebProxy(WebProxySettings? settings)
{
return settings != null ? new WebProxyModel
{
Address = settings.Address,
UserName = settings.UserName,
Password = settings.Password
} : null;
}
private static IDictionary<string, object> MapHeaders(IDictionary<string, WireMockList<string>> dictionary)
{
var newDictionary = new Dictionary<string, object>();

View File

@@ -280,12 +280,8 @@ public partial class WireMockServer
{
Url = responseModel.ProxyUrl!,
ClientX509Certificate2ThumbprintOrSubjectName = responseModel.X509Certificate2ThumbprintOrSubjectName,
WebProxySettings = responseModel.WebProxy != null ? new WebProxySettings
{
Address = responseModel.WebProxy.Address,
UserName = responseModel.WebProxy.UserName,
Password = responseModel.WebProxy.Password
} : null
WebProxySettings = TinyMapperUtils.Instance.Map(responseModel.WebProxy),
ReplaceSettings = TinyMapperUtils.Instance.Map(responseModel.ProxyUrlReplaceSettings)
};
return responseBuilder.WithProxy(proxyAndRecordSettings);

View File

@@ -10,7 +10,7 @@ using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Util;
using Stef.Validation;
using OrgMappings = WireMock.Org.Abstractions.Mappings;
using OrgMapping = WireMock.Org.Abstractions.Mapping;
namespace WireMock.Server;
@@ -25,14 +25,14 @@ public partial class WireMockServer
{
Guard.NotNull(path, nameof(path));
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
var filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
{
var mappings = DeserializeJsonToArray<OrgMappings>(value);
var mappings = DeserializeJsonToArray<OrgMapping>(value);
foreach (var mapping in mappings)
{
if (mappings.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
if (mappings.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
{
ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mapping, guidFromFilename, path);
}
@@ -48,10 +48,10 @@ public partial class WireMockServer
{
try
{
var mappingModels = DeserializeRequestMessageToArray<OrgMappings>(requestMessage);
var mappingModels = DeserializeRequestMessageToArray<OrgMapping>(requestMessage);
if (mappingModels.Length == 1)
{
Guid? guid = ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModels[0]);
var guid = ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModels[0]);
return ResponseMessageBuilder.Create(201, "Mapping added", guid);
}
@@ -74,7 +74,7 @@ public partial class WireMockServer
}
}
private Guid? ConvertWireMockOrgMappingAndRegisterAsRespondProvider(OrgMappings mapping, Guid? guid = null, string? path = null)
private Guid? ConvertWireMockOrgMappingAndRegisterAsRespondProvider(Org.Abstractions.Mapping mapping, Guid? guid = null, string? path = null)
{
var requestBuilder = Request.Create();
@@ -159,7 +159,7 @@ public partial class WireMockServer
}
}
IResponseBuilder responseBuilder = Response.Create();
var responseBuilder = Response.Create();
var response = mapping.Response;
if (response != null)

View File

@@ -31,6 +31,11 @@ public partial class WireMockServer
proxyRespondProvider.AtPriority(WireMockConstants.ProxyPriority);
}
if(settings.ProxyAndRecordSettings.ProxyAll)
{
proxyRespondProvider.AtPriority(int.MinValue);
}
proxyRespondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
}

View File

@@ -427,6 +427,8 @@ public partial class WireMockServer : IWireMockServer
{
ResetLogEntries();
ResetScenarios();
ResetMappings();
}

View File

@@ -94,4 +94,10 @@ public class ProxyAndRecordSettings : HttpClientSettings
/// Append an unique GUID to the filename from the saved mapping file.
/// </summary>
public bool AppendGuidToSavedMappingFile { get; set; }
/// <summary>
/// Proxy all Api calls, irrespective of any condition
/// </summary>
[PublicAPI]
public bool ProxyAll { get; set; } = false;
}

View File

@@ -125,7 +125,8 @@ public static class WireMockServerSettingsParser
{
StatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern", "*"),
// HttpMethods = new ProxySaveMappingSetting<string[]>(parser.GetValues("DoNotSaveMappingForHttpMethods", new string[0]), MatchBehaviour.RejectOnMatch)
}
},
ProxyAll = parser.GetBoolValue(nameof(ProxyAndRecordSettings.ProxyAll))
};
ParseWebProxyAddressSettings(proxyAndRecordSettings, parser);

View File

@@ -5,7 +5,6 @@ using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
@@ -250,7 +249,7 @@ internal class Transformer : ITransformer
return;
}
var transformed = transformerContext.ParseAndEvaluate(stringValue, model);
var transformed = transformerContext.ParseAndEvaluate(stringValue!, model);
if (!Equals(stringValue, transformed))
{
ReplaceNodeValue(options, node, transformed);

View File

@@ -1,4 +1,5 @@
using Nelibur.ObjectMapper;
using WireMock.Admin.Mappings;
using WireMock.Admin.Settings;
using WireMock.Settings;
@@ -12,10 +13,12 @@ internal sealed class TinyMapperUtils
{
TinyMapper.Bind<ProxyAndRecordSettings, ProxyAndRecordSettingsModel>();
TinyMapper.Bind<WebProxySettings, WebProxySettingsModel>();
TinyMapper.Bind<WebProxySettings, WebProxyModel>();
TinyMapper.Bind<ProxyUrlReplaceSettings, ProxyUrlReplaceSettingsModel>();
TinyMapper.Bind<ProxyAndRecordSettingsModel, ProxyAndRecordSettings>();
TinyMapper.Bind<WebProxySettingsModel, WebProxySettings>();
TinyMapper.Bind<WebProxyModel, WebProxySettings>();
TinyMapper.Bind<ProxyUrlReplaceSettingsModel, ProxyUrlReplaceSettings>();
}
@@ -28,4 +31,24 @@ internal sealed class TinyMapperUtils
{
return model == null ? null : TinyMapper.Map<ProxyAndRecordSettings>(model);
}
public ProxyUrlReplaceSettingsModel? Map(ProxyUrlReplaceSettings? instance)
{
return instance == null ? null : TinyMapper.Map<ProxyUrlReplaceSettingsModel>(instance);
}
public ProxyUrlReplaceSettings? Map(ProxyUrlReplaceSettingsModel? model)
{
return model == null ? null : TinyMapper.Map<ProxyUrlReplaceSettings>(model);
}
public WebProxyModel? Map(WebProxySettings? instance)
{
return instance == null ? null : TinyMapper.Map<WebProxyModel>(instance);
}
public WebProxySettings? Map(WebProxyModel? model)
{
return model == null ? null : TinyMapper.Map<WebProxySettings>(model);
}
}

View File

@@ -80,7 +80,7 @@
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">
<PackageReference Include="XPath2.Extensions" Version="1.1.3" />
<PackageReference Include="XPath2.Extensions" Version="1.1.4" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.12.2" />
</ItemGroup>
@@ -189,13 +189,13 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.0" />
<PackageReference Include="Handlebars.Net.Helpers" Version="2.4.1.2" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.4.1.2" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.4.1.2" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.4.1.2" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.4.1.2" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.4.1.2" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.4.1.2" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,9 +1,8 @@
namespace WireMock.Org.Abstractions
{
public class GetAdminMappingsResult
{
public Mappings Mappings { get; set; }
namespace WireMock.Org.Abstractions;
public Meta Meta { get; set; }
}
public class GetAdminMappingsResult
{
public Mapping[] Mappings { get; set; }
public Meta Meta { get; set; }
}

View File

@@ -0,0 +1,58 @@
namespace WireMock.Org.Abstractions;
public class Mapping
{
/// <summary>
/// This stub mapping's unique identifier
/// </summary>
public string Id { get; set; }
/// <summary>
/// Alias for the id
/// </summary>
public string Uuid { get; set; }
/// <summary>
/// The stub mapping's name
/// </summary>
public string Name { get; set; }
public MappingsRequest Request { get; set; }
public MappingsResponse Response { get; set; }
/// <summary>
/// Indicates that the stub mapping should be persisted immediately on create/update/delete and survive resets to default.
/// </summary>
public bool Persistent { get; set; }
/// <summary>
/// This stub mapping's priority relative to others. 1 is highest.
/// </summary>
public int Priority { get; set; }
/// <summary>
/// The name of the scenario that this stub mapping is part of
/// </summary>
public string ScenarioName { get; set; }
/// <summary>
/// The required state of the scenario in order for this stub to be matched.
/// </summary>
public string RequiredScenarioState { get; set; }
/// <summary>
/// The new state for the scenario to be updated to after this stub is served.
/// </summary>
public string NewScenarioState { get; set; }
/// <summary>
/// A map of the names of post serve action extensions to trigger and their parameters.
/// </summary>
public object PostServeActions { get; set; }
/// <summary>
/// Arbitrary metadata to be used for e.g. tagging, documentation. Can also be used to find and remove stubs.
/// </summary>
public object Metadata { get; set; }
}

View File

@@ -1,59 +0,0 @@
namespace WireMock.Org.Abstractions
{
public class Mappings
{
/// <summary>
/// This stub mapping's unique identifier
/// </summary>
public string Id { get; set; }
/// <summary>
/// Alias for the id
/// </summary>
public string Uuid { get; set; }
/// <summary>
/// The stub mapping's name
/// </summary>
public string Name { get; set; }
public MappingsRequest Request { get; set; }
public MappingsResponse Response { get; set; }
/// <summary>
/// Indicates that the stub mapping should be persisted immediately on create/update/delete and survive resets to default.
/// </summary>
public bool Persistent { get; set; }
/// <summary>
/// This stub mapping's priority relative to others. 1 is highest.
/// </summary>
public int Priority { get; set; }
/// <summary>
/// The name of the scenario that this stub mapping is part of
/// </summary>
public string ScenarioName { get; set; }
/// <summary>
/// The required state of the scenario in order for this stub to be matched.
/// </summary>
public string RequiredScenarioState { get; set; }
/// <summary>
/// The new state for the scenario to be updated to after this stub is served.
/// </summary>
public string NewScenarioState { get; set; }
/// <summary>
/// A map of the names of post serve action extensions to trigger and their parameters.
/// </summary>
public object PostServeActions { get; set; }
/// <summary>
/// Arbitrary metadata to be used for e.g. tagging, documentation. Can also be used to find and remove stubs.
/// </summary>
public object Metadata { get; set; }
}
}

View File

@@ -1,9 +1,8 @@
namespace WireMock.Org.Abstractions
{
public class PostAdminMappingsFindByMetadataResult
{
public Mappings Mappings { get; set; }
namespace WireMock.Org.Abstractions;
public Meta Meta { get; set; }
}
public class PostAdminMappingsFindByMetadataResult
{
public Mapping[] Mappings { get; set; }
public Meta Meta { get; set; }
}

View File

@@ -1,9 +1,8 @@
namespace WireMock.Org.Abstractions
{
public class PostAdminRecordingsSnapshotResult
{
public Mappings Mappings { get; set; }
namespace WireMock.Org.Abstractions;
public Meta Meta { get; set; }
}
public class PostAdminRecordingsSnapshotResult
{
public Mapping[] Mappings { get; set; }
public Meta Meta { get; set; }
}

View File

@@ -1,9 +1,8 @@
namespace WireMock.Org.Abstractions
{
public class PostAdminRecordingsStopResult
{
public Mappings Mappings { get; set; }
namespace WireMock.Org.Abstractions;
public Meta Meta { get; set; }
}
public class PostAdminRecordingsStopResult
{
public Mapping[] Mappings { get; set; }
public Meta Meta { get; set; }
}

View File

@@ -1,299 +1,293 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using AnyOfTypes;
using RestEase;
using WireMock.Org.Abstractions;
namespace WireMock.Org.RestClient
namespace WireMock.Org.RestClient;
/// <summary>
/// Summary: WireMockOrg
///
/// Title : WireMock
/// Version: 2.3x
/// </summary>
public interface IWireMockOrgApi
{
/// <summary>
/// Summary: WireMockOrg
/// Get all stub mappings
///
/// Title : WireMock
/// Version: 2.33.2
/// GetAdminMappings (/__admin/mappings)
/// </summary>
public interface IWireMockOrgApi
{
/// <summary>
/// Get all stub mappings
///
/// GetAdminMappings (/__admin/mappings)
/// </summary>
/// <param name="limit">The maximum number of results to return</param>
/// <param name="offset">The start index of the results to return</param>
[Get("/__admin/mappings")]
Task<GetAdminMappingsResult> GetAdminMappingsAsync([Query] int? limit, [Query] int? offset);
/// <param name="limit">The maximum number of results to return</param>
/// <param name="offset">The start index of the results to return</param>
[Get("/__admin/mappings")]
Task<GetAdminMappingsResult> GetAdminMappingsAsync([Query] int? limit, [Query] int? offset);
/// <summary>
/// Create a new stub mapping
///
/// PostAdminMappings (/__admin/mappings)
/// </summary>
[Post("/__admin/mappings")]
[Header("Content-Type", "application/json")]
Task<PostAdminMappingsResult> PostAdminMappingsAsync();
/// <summary>
/// Create a new stub mapping
///
/// PostAdminMappings (/__admin/mappings)
/// </summary>
[Post("/__admin/mappings")]
[Header("Content-Type", "application/json")]
Task<PostAdminMappingsResult> PostAdminMappingsAsync();
/// <summary>
/// Delete all stub mappings
///
/// DeleteAdminMappings (/__admin/mappings)
/// </summary>
[Delete("/__admin/mappings")]
Task<object> DeleteAdminMappingsAsync();
/// <summary>
/// Delete all stub mappings
///
/// DeleteAdminMappings (/__admin/mappings)
/// </summary>
[Delete("/__admin/mappings")]
Task<object> DeleteAdminMappingsAsync();
/// <summary>
/// Reset stub mappings
///
/// PostAdminMappingsReset (/__admin/mappings/reset)
/// </summary>
[Post("/__admin/mappings/reset")]
Task<object> PostAdminMappingsResetAsync();
/// <summary>
/// Reset stub mappings
///
/// PostAdminMappingsReset (/__admin/mappings/reset)
/// </summary>
[Post("/__admin/mappings/reset")]
Task<object> PostAdminMappingsResetAsync();
/// <summary>
/// Persist stub mappings
///
/// PostAdminMappingsSave (/__admin/mappings/save)
/// </summary>
[Post("/__admin/mappings/save")]
Task<object> PostAdminMappingsSaveAsync();
/// <summary>
/// Persist stub mappings
///
/// PostAdminMappingsSave (/__admin/mappings/save)
/// </summary>
[Post("/__admin/mappings/save")]
Task<object> PostAdminMappingsSaveAsync();
/// <summary>
/// Get stub mapping by ID
///
/// GetAdminMappingsByStubMappingId (/__admin/mappings/{stubMappingId})
/// </summary>
/// <param name="stubMappingId">The UUID of stub mapping</param>
[Get("/__admin/mappings/{stubMappingId}")]
Task<Response<AnyOf<GetAdminMappingsByStubMappingIdResult, object>>> GetAdminMappingsByStubMappingIdAsync([Path] string stubMappingId);
/// <summary>
/// Get stub mapping by ID
///
/// GetAdminMappingsByStubMappingId (/__admin/mappings/{stubMappingId})
/// </summary>
/// <param name="stubMappingId">The UUID of stub mapping</param>
[Get("/__admin/mappings/{stubMappingId}")]
Task<Response<AnyOf<GetAdminMappingsByStubMappingIdResult, object>>> GetAdminMappingsByStubMappingIdAsync([Path] string stubMappingId);
/// <summary>
/// Update a stub mapping
///
/// PutAdminMappingsByStubMappingId (/__admin/mappings/{stubMappingId})
/// </summary>
/// <param name="stubMappingId">The UUID of stub mapping</param>
[Put("/__admin/mappings/{stubMappingId}")]
[Header("Content-Type", "application/json")]
Task<Response<AnyOf<PutAdminMappingsByStubMappingIdResult, object>>> PutAdminMappingsByStubMappingIdAsync([Path] string stubMappingId);
/// <summary>
/// Update a stub mapping
///
/// PutAdminMappingsByStubMappingId (/__admin/mappings/{stubMappingId})
/// </summary>
/// <param name="stubMappingId">The UUID of stub mapping</param>
[Put("/__admin/mappings/{stubMappingId}")]
[Header("Content-Type", "application/json")]
Task<Response<AnyOf<PutAdminMappingsByStubMappingIdResult, object>>> PutAdminMappingsByStubMappingIdAsync([Path] string stubMappingId);
/// <summary>
/// Delete a stub mapping
///
/// DeleteAdminMappingsByStubMappingId (/__admin/mappings/{stubMappingId})
/// </summary>
/// <param name="stubMappingId">The UUID of stub mapping</param>
[Delete("/__admin/mappings/{stubMappingId}")]
Task<object> DeleteAdminMappingsByStubMappingIdAsync([Path] string stubMappingId);
/// <summary>
/// Delete a stub mapping
///
/// DeleteAdminMappingsByStubMappingId (/__admin/mappings/{stubMappingId})
/// </summary>
/// <param name="stubMappingId">The UUID of stub mapping</param>
[Delete("/__admin/mappings/{stubMappingId}")]
Task<object> DeleteAdminMappingsByStubMappingIdAsync([Path] string stubMappingId);
/// <summary>
/// Find stubs by matching on their metadata
///
/// PostAdminMappingsFindByMetadata (/__admin/mappings/find-by-metadata)
/// </summary>
[Post("/__admin/mappings/find-by-metadata")]
[Header("Content-Type", "application/json")]
Task<PostAdminMappingsFindByMetadataResult> PostAdminMappingsFindByMetadataAsync();
/// <summary>
/// Find stubs by matching on their metadata
///
/// PostAdminMappingsFindByMetadata (/__admin/mappings/find-by-metadata)
/// </summary>
[Post("/__admin/mappings/find-by-metadata")]
[Header("Content-Type", "application/json")]
Task<PostAdminMappingsFindByMetadataResult> PostAdminMappingsFindByMetadataAsync();
/// <summary>
/// Delete stub mappings matching metadata
///
/// PostAdminMappingsRemoveByMetadata (/__admin/mappings/remove-by-metadata)
/// </summary>
[Post("/__admin/mappings/remove-by-metadata")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminMappingsRemoveByMetadataAsync();
/// <summary>
/// Delete stub mappings matching metadata
///
/// PostAdminMappingsRemoveByMetadata (/__admin/mappings/remove-by-metadata)
/// </summary>
[Post("/__admin/mappings/remove-by-metadata")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminMappingsRemoveByMetadataAsync();
/// <summary>
/// Get all requests in journal
///
/// GetAdminRequests (/__admin/requests)
/// </summary>
/// <param name="limit">The maximum number of results to return</param>
/// <param name="since">Only return logged requests after this date</param>
[Get("/__admin/requests")]
Task<object> GetAdminRequestsAsync([Query] string limit, [Query] string since);
/// <summary>
/// Get all requests in journal
///
/// GetAdminRequests (/__admin/requests)
/// </summary>
/// <param name="limit">The maximum number of results to return</param>
/// <param name="since">Only return logged requests after this date</param>
[Get("/__admin/requests")]
Task<object> GetAdminRequestsAsync([Query] string limit, [Query] string since);
/// <summary>
/// Delete all requests in journal
///
/// DeleteAdminRequests (/__admin/requests)
/// </summary>
[Delete("/__admin/requests")]
Task<object> DeleteAdminRequestsAsync();
/// <summary>
/// Delete all requests in journal
///
/// DeleteAdminRequests (/__admin/requests)
/// </summary>
[Delete("/__admin/requests")]
Task<object> DeleteAdminRequestsAsync();
/// <summary>
/// Get request by ID
///
/// GetAdminRequestsByRequestId (/__admin/requests/{requestId})
/// </summary>
/// <param name="requestId">The UUID of the logged request</param>
[Get("/__admin/requests/{requestId}")]
Task<object> GetAdminRequestsByRequestIdAsync([Path] string requestId);
/// <summary>
/// Get request by ID
///
/// GetAdminRequestsByRequestId (/__admin/requests/{requestId})
/// </summary>
/// <param name="requestId">The UUID of the logged request</param>
[Get("/__admin/requests/{requestId}")]
Task<object> GetAdminRequestsByRequestIdAsync([Path] string requestId);
/// <summary>
/// Delete request by ID
///
/// DeleteAdminRequestsByRequestId (/__admin/requests/{requestId})
/// </summary>
/// <param name="requestId">The UUID of the logged request</param>
[Delete("/__admin/requests/{requestId}")]
Task<object> DeleteAdminRequestsByRequestIdAsync([Path] string requestId);
/// <summary>
/// Delete request by ID
///
/// DeleteAdminRequestsByRequestId (/__admin/requests/{requestId})
/// </summary>
/// <param name="requestId">The UUID of the logged request</param>
[Delete("/__admin/requests/{requestId}")]
Task<object> DeleteAdminRequestsByRequestIdAsync([Path] string requestId);
/// <summary>
/// Empty the request journal
///
/// PostAdminRequestsReset (/__admin/requests/reset)
/// </summary>
[Post("/__admin/requests/reset")]
Task<object> PostAdminRequestsResetAsync();
/// <summary>
/// Empty the request journal
///
/// PostAdminRequestsReset (/__admin/requests/reset)
/// </summary>
[Post("/__admin/requests/reset")]
Task<object> PostAdminRequestsResetAsync();
/// <summary>
/// Count requests by criteria
///
/// PostAdminRequestsCount (/__admin/requests/count)
/// </summary>
[Post("/__admin/requests/count")]
[Header("Content-Type", "application/json")]
Task<PostAdminRequestsCountResult> PostAdminRequestsCountAsync();
/// <summary>
/// Count requests by criteria
///
/// PostAdminRequestsCount (/__admin/requests/count)
/// </summary>
[Post("/__admin/requests/count")]
[Header("Content-Type", "application/json")]
Task<PostAdminRequestsCountResult> PostAdminRequestsCountAsync();
/// <summary>
/// Remove requests by criteria
///
/// PostAdminRequestsRemove (/__admin/requests/remove)
/// </summary>
[Post("/__admin/requests/remove")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRequestsRemoveAsync();
/// <summary>
/// Remove requests by criteria
///
/// PostAdminRequestsRemove (/__admin/requests/remove)
/// </summary>
[Post("/__admin/requests/remove")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRequestsRemoveAsync();
/// <summary>
/// Delete requests mappings matching metadata
///
/// PostAdminRequestsRemoveByMetadata (/__admin/requests/remove-by-metadata)
/// </summary>
[Post("/__admin/requests/remove-by-metadata")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRequestsRemoveByMetadataAsync();
/// <summary>
/// Delete requests mappings matching metadata
///
/// PostAdminRequestsRemoveByMetadata (/__admin/requests/remove-by-metadata)
/// </summary>
[Post("/__admin/requests/remove-by-metadata")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRequestsRemoveByMetadataAsync();
/// <summary>
/// Find requests by criteria
///
/// PostAdminRequestsFind (/__admin/requests/find)
/// </summary>
[Post("/__admin/requests/find")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRequestsFindAsync();
/// <summary>
/// Find requests by criteria
///
/// PostAdminRequestsFind (/__admin/requests/find)
/// </summary>
[Post("/__admin/requests/find")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRequestsFindAsync();
/// <summary>
/// Find unmatched requests
///
/// GetAdminRequestsUnmatched (/__admin/requests/unmatched)
/// </summary>
[Get("/__admin/requests/unmatched")]
Task<object> GetAdminRequestsUnmatchedAsync();
/// <summary>
/// Find unmatched requests
///
/// GetAdminRequestsUnmatched (/__admin/requests/unmatched)
/// </summary>
[Get("/__admin/requests/unmatched")]
Task<object> GetAdminRequestsUnmatchedAsync();
/// <summary>
/// Retrieve near-misses for all unmatched requests
///
/// GetAdminRequestsUnmatchedNearMisses (/__admin/requests/unmatched/near-misses)
/// </summary>
[Get("/__admin/requests/unmatched/near-misses")]
Task<GetAdminRequestsUnmatchedNearMissesResult> GetAdminRequestsUnmatchedNearMissesAsync();
/// <summary>
/// Retrieve near-misses for all unmatched requests
///
/// GetAdminRequestsUnmatchedNearMisses (/__admin/requests/unmatched/near-misses)
/// </summary>
[Get("/__admin/requests/unmatched/near-misses")]
Task<GetAdminRequestsUnmatchedNearMissesResult> GetAdminRequestsUnmatchedNearMissesAsync();
/// <summary>
/// Find near misses matching specific request
///
/// PostAdminNearMissesRequest (/__admin/near-misses/request)
/// </summary>
[Post("/__admin/near-misses/request")]
[Header("Content-Type", "application/json")]
Task<PostAdminNearMissesRequestResult> PostAdminNearMissesRequestAsync();
/// <summary>
/// Find near misses matching specific request
///
/// PostAdminNearMissesRequest (/__admin/near-misses/request)
/// </summary>
[Post("/__admin/near-misses/request")]
[Header("Content-Type", "application/json")]
Task<PostAdminNearMissesRequestResult> PostAdminNearMissesRequestAsync();
/// <summary>
/// Find near misses matching request pattern
///
/// PostAdminNearMissesRequestPattern (/__admin/near-misses/request-pattern)
/// </summary>
[Post("/__admin/near-misses/request-pattern")]
[Header("Content-Type", "application/json")]
Task<PostAdminNearMissesRequestPatternResult> PostAdminNearMissesRequestPatternAsync();
/// <summary>
/// Find near misses matching request pattern
///
/// PostAdminNearMissesRequestPattern (/__admin/near-misses/request-pattern)
/// </summary>
[Post("/__admin/near-misses/request-pattern")]
[Header("Content-Type", "application/json")]
Task<PostAdminNearMissesRequestPatternResult> PostAdminNearMissesRequestPatternAsync();
/// <summary>
/// Start recording
///
/// PostAdminRecordingsStart (/__admin/recordings/start)
/// </summary>
[Post("/__admin/recordings/start")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRecordingsStartAsync();
/// <summary>
/// Start recording
///
/// PostAdminRecordingsStart (/__admin/recordings/start)
/// </summary>
[Post("/__admin/recordings/start")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminRecordingsStartAsync();
/// <summary>
/// Stop recording
///
/// PostAdminRecordingsStop (/__admin/recordings/stop)
/// </summary>
[Post("/__admin/recordings/stop")]
Task<PostAdminRecordingsStopResult> PostAdminRecordingsStopAsync();
/// <summary>
/// Stop recording
///
/// PostAdminRecordingsStop (/__admin/recordings/stop)
/// </summary>
[Post("/__admin/recordings/stop")]
Task<PostAdminRecordingsStopResult> PostAdminRecordingsStopAsync();
/// <summary>
/// Get recording status
///
/// GetAdminRecordingsStatus (/__admin/recordings/status)
/// </summary>
[Get("/__admin/recordings/status")]
Task<GetAdminRecordingsStatusResult> GetAdminRecordingsStatusAsync();
/// <summary>
/// Get recording status
///
/// GetAdminRecordingsStatus (/__admin/recordings/status)
/// </summary>
[Get("/__admin/recordings/status")]
Task<GetAdminRecordingsStatusResult> GetAdminRecordingsStatusAsync();
/// <summary>
/// Take a snapshot recording
///
/// PostAdminRecordingsSnapshot (/__admin/recordings/snapshot)
/// </summary>
[Post("/__admin/recordings/snapshot")]
[Header("Content-Type", "application/json")]
Task<PostAdminRecordingsSnapshotResult> PostAdminRecordingsSnapshotAsync();
/// <summary>
/// Take a snapshot recording
///
/// PostAdminRecordingsSnapshot (/__admin/recordings/snapshot)
/// </summary>
[Post("/__admin/recordings/snapshot")]
[Header("Content-Type", "application/json")]
Task<PostAdminRecordingsSnapshotResult> PostAdminRecordingsSnapshotAsync();
/// <summary>
/// Get all scenarios
///
/// GetAdminScenarios (/__admin/scenarios)
/// </summary>
[Get("/__admin/scenarios")]
Task<GetAdminScenariosResult> GetAdminScenariosAsync();
/// <summary>
/// Get all scenarios
///
/// GetAdminScenarios (/__admin/scenarios)
/// </summary>
[Get("/__admin/scenarios")]
Task<GetAdminScenariosResult> GetAdminScenariosAsync();
/// <summary>
/// Reset the state of all scenarios
///
/// PostAdminScenariosReset (/__admin/scenarios/reset)
/// </summary>
[Post("/__admin/scenarios/reset")]
Task<object> PostAdminScenariosResetAsync();
/// <summary>
/// Reset the state of all scenarios
///
/// PostAdminScenariosReset (/__admin/scenarios/reset)
/// </summary>
[Post("/__admin/scenarios/reset")]
Task<object> PostAdminScenariosResetAsync();
/// <summary>
/// Update global settings
///
/// PostAdminSettings (/__admin/settings)
/// </summary>
[Post("/__admin/settings")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminSettingsAsync();
/// <summary>
/// Update global settings
///
/// PostAdminSettings (/__admin/settings)
/// </summary>
[Post("/__admin/settings")]
[Header("Content-Type", "application/json")]
Task<object> PostAdminSettingsAsync();
/// <summary>
/// Reset mappings and request journal
///
/// PostAdminReset (/__admin/reset)
/// </summary>
[Post("/__admin/reset")]
Task<object> PostAdminResetAsync();
/// <summary>
/// Reset mappings and request journal
///
/// PostAdminReset (/__admin/reset)
/// </summary>
[Post("/__admin/reset")]
Task<object> PostAdminResetAsync();
/// <summary>
/// Shutdown the WireMock server
///
/// PostAdminShutdown (/__admin/shutdown)
/// </summary>
[Post("/__admin/shutdown")]
Task<object> PostAdminShutdownAsync();
}
/// <summary>
/// Shutdown the WireMock server
///
/// PostAdminShutdown (/__admin/shutdown)
/// </summary>
[Post("/__admin/shutdown")]
Task<object> PostAdminShutdownAsync();
}

View File

@@ -0,0 +1,68 @@
using System;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using Newtonsoft.Json.Linq;
using WireMock.Handlers;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders;
public class ResponseWithHandlebarsDateTimeTests
{
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new();
private readonly Mock<IMapping> _mappingMock;
public ResponseWithHandlebarsDateTimeTests()
{
_mappingMock = new Mock<IMapping>();
var filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
_settings.FileSystemHandler = filesystemHandlerMock.Object;
}
[Fact]
public async Task Response_WithBodyAsJson_ProvideResponseAsync_Handlebars_DateTime()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
DateTimeYear = "{{ DateTime.UtcNow \"yyyy\" }}"
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
var j = JObject.FromObject(response.Message.BodyData!.BodyAsJson!);
j["DateTimeYear"]!.Value<string>().Should().Be(DateTime.Now.Year.ToString());
}
[Fact]
public async Task Response_WithBody_ProvideResponseAsync_Handlebars_DateTime()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBody("{\nDateTimeYear = \"{{ DateTime.UtcNow \"yyyy\" }}\"")
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
response.Message.BodyData!.BodyAsString.Should().Contain($"DateTimeYear = \"{DateTime.Now.Year}\"");
}
}

View File

@@ -1,5 +1,6 @@
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using Newtonsoft.Json.Linq;
using NFluent;
@@ -149,7 +150,7 @@ public class ResponseWithHandlebarsRandomTests
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random2()
public async Task Response_ProvideResponseAsync_Handlebars_Random_Integer()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
@@ -168,4 +169,25 @@ public class ResponseWithHandlebarsRandomTests
JObject j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
Check.That(j["Integer"].Value<int>()).IsStrictlyGreaterThan(10000000).And.IsStrictlyLessThan(99999999);
}
[Fact]
public async Task Response_ProvideResponseAsync_Handlebars_Random_Long()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
var responseBuilder = Response.Create()
.WithBodyAsJson(new
{
Long = "{{#Random Type=\"Long\" Min=1000000000 Max=9999999999}}{{this}}{{/Random}}",
})
.WithTransformer();
// Act
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
// Assert
var j = JObject.FromObject(response.Message.BodyData.BodyAsJson);
j["Long"].Value<long>().Should().BeInRange(1000000000, 9999999999);
}
}

View File

@@ -0,0 +1,30 @@
{
Guid: 90356dba-b36c-469a-a17e-669cd84f1f05,
UpdatedAt: DateTime_1,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: /1,
IgnoreCase: false
}
]
},
Body: {
Matcher: {
Name: RegexMatcher,
Pattern: hello,
IgnoreCase: true
}
}
},
Response: {
ProxyUrl: https://my-proxy.com,
ProxyUrlReplaceSettings: {
OldValue: x,
NewValue: y,
IgnoreCase: true
}
}
}

View File

@@ -351,6 +351,57 @@ public class WireMockAdminApiTests
server.Stop();
}
[Fact]
public async Task IWireMockAdminApi_GetMappingAsync_WithProxy_And_ProxyUrlReplaceSettings()
{
// Arrange
var guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05");
var server = WireMockServer.StartWithAdminInterface();
var api = RestClient.For<IWireMockAdminApi>(server.Url);
// Act
var model = new MappingModel
{
Guid = guid,
Request = new RequestModel
{
Path = "/1",
Body = new BodyModel
{
Matcher = new MatcherModel
{
Name = "RegexMatcher",
Pattern = "hello",
IgnoreCase = true
}
}
},
Response = new ResponseModel
{
ProxyUrl = "https://my-proxy.com",
ProxyUrlReplaceSettings = new ProxyUrlReplaceSettingsModel
{
OldValue = "x",
NewValue = "y",
IgnoreCase = true
}
}
};
var postMappingResult = await api.PostMappingAsync(model).ConfigureAwait(false);
// Assert
postMappingResult.Should().NotBeNull();
var mapping = server.Mappings.FirstOrDefault(m => m.Guid == guid);
mapping.Should().NotBeNull();
var getMappingResult = await api.GetMappingAsync(guid).ConfigureAwait(false);
await Verifier.Verify(getMappingResult, VerifySettings).DontScrubGuids();
server.Stop();
}
[Fact]
public async Task IWireMockAdminApi_GetRequestsAsync_Json()
{

View File

@@ -922,4 +922,49 @@ public class WireMockServerProxyTests
server.LogEntries.Should().HaveCount(1);
server.Stop();
}
[Fact]
public async Task WireMockServer_ProxyAndRecordSettings_SameRequest_ShouldProxyAll()
{
//Arrange
var wireMockServerSettings = new WireMockServerSettings
{
Urls = new[] { "http://localhost:9091" },
ProxyAndRecordSettings = new ProxyAndRecordSettings
{
Url = "http://postman-echo.com",
SaveMapping = true,
ProxyAll = true,
SaveMappingToFile = false,
ExcludedHeaders = new[] { "Postman-Token" },
ExcludedCookies = new[] { "sails.sid" }
}
};
var server = WireMockServer.Start(wireMockServerSettings);
var requestBody = "{\"key1\": \"value1\", \"key2\": \"value2\"}";
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost:9091/post"),
Content = new StringContent(requestBody)
};
var request2 = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("http://localhost:9091/post"),
Content = new StringContent(requestBody)
};
server.ResetMappings();
//Act
await new HttpClient().SendAsync(request);
await new HttpClient().SendAsync(request2);
//Assert
Check.That(server.Mappings.Count()).IsEqualTo(3);
server.Dispose();
}
}