From 31261ec45d025bbea3a034922cbf7c8626580681 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Tue, 9 May 2017 21:43:10 +0200 Subject: [PATCH] Initial code for proxy and record #27 --- WireMock.Net Solution.sln | 7 ++++ .../Program.cs | 1 + .../Program.cs | 32 ++++++++++++++++ ...eMock.Net.Console.Record.NETCoreApp.csproj | 19 ++++++++++ .../Program.cs | 1 + .../Program.cs | 1 + src/WireMock.Net.StandAlone/Program.cs | 1 + src/WireMock.Net/DynamicResponseProvider.cs | 38 +++++++++++++++++++ src/WireMock.Net/Mapping.cs | 2 +- .../Server/FluentMockServer.Admin.cs | 17 +++++++++ src/WireMock.Net/Server/FluentMockServer.cs | 8 +++- .../Server/IRespondWithAProvider.cs | 11 ++++-- .../FluentMockServerSettings.cs | 14 ++++--- .../Settings/ProxyAndRecordSettings.cs | 18 +++++++++ 14 files changed, 160 insertions(+), 10 deletions(-) create mode 100644 examples/WireMock.Net.Console.Record.NETCoreApp/Program.cs create mode 100644 examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj rename src/WireMock.Net/{Server => Settings}/FluentMockServerSettings.cs (75%) create mode 100644 src/WireMock.Net/Settings/ProxyAndRecordSettings.cs diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln index 94648ab88..e26675b6b 100644 --- a/WireMock.Net Solution.sln +++ b/WireMock.Net Solution.sln @@ -35,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.NET EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.NETCoreApp", "examples\WireMock.Net.Console.NETCoreApp\WireMock.Net.Console.NETCoreApp.csproj", "{FE281639-B014-4C8A-96FA-141164A74713}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Record.NETCoreApp", "examples\WireMock.Net.Console.Record.NETCoreApp\WireMock.Net.Console.Record.NETCoreApp.csproj", "{1995E414-F197-4AB4-90C2-68D806B5AF59}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,6 +67,10 @@ Global {FE281639-B014-4C8A-96FA-141164A74713}.Debug|Any CPU.Build.0 = Debug|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Release|Any CPU.ActiveCfg = Release|Any CPU {FE281639-B014-4C8A-96FA-141164A74713}.Release|Any CPU.Build.0 = Release|Any CPU + {1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -76,5 +82,6 @@ Global {31DC2EF8-C3FE-467D-84BE-FB5D956E612E} = {890A1DED-C229-4FA1-969E-AAC3BBFC05E5} {14D7298C-2BE5-42C3-A3D5-9433E77218F9} = {EF242EDF-7133-4277-9A0C-18744DE08707} {FE281639-B014-4C8A-96FA-141164A74713} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A} + {1995E414-F197-4AB4-90C2-68D806B5AF59} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A} EndGlobalSection EndGlobal diff --git a/examples/WireMock.Net.Console.NETCoreApp/Program.cs b/examples/WireMock.Net.Console.NETCoreApp/Program.cs index 6718b4841..6afcf5d01 100644 --- a/examples/WireMock.Net.Console.NETCoreApp/Program.cs +++ b/examples/WireMock.Net.Console.NETCoreApp/Program.cs @@ -5,6 +5,7 @@ using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; +using WireMock.Settings; namespace WireMock.Net.Console.NETCoreApp { diff --git a/examples/WireMock.Net.Console.Record.NETCoreApp/Program.cs b/examples/WireMock.Net.Console.Record.NETCoreApp/Program.cs new file mode 100644 index 000000000..0b042024f --- /dev/null +++ b/examples/WireMock.Net.Console.Record.NETCoreApp/Program.cs @@ -0,0 +1,32 @@ +using Newtonsoft.Json; +using WireMock.Server; +using WireMock.Settings; + +namespace WireMock.Net.Console.NETCoreApp +{ + static class Program + { + static void Main(params string[] args) + { + string url1 = "http://localhost:9095/"; + + var server = FluentMockServer.Start(new FluentMockServerSettings + { + Urls = new[] { url1 }, + StartAdminInterface = true, + ProxyAndRecordSettings = new ProxyAndRecordSettings { Url = "http://www.bbc.com" } + }); + + System.Console.WriteLine("Press any key to stop the server"); + System.Console.ReadKey(); + server.Stop(); + + System.Console.WriteLine("Displaying all requests"); + var allRequests = server.LogEntries; + System.Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented)); + + System.Console.WriteLine("Press any key to quit"); + System.Console.ReadKey(); + } + } +} \ No newline at end of file diff --git a/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj b/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj new file mode 100644 index 000000000..bc52b49ef --- /dev/null +++ b/examples/WireMock.Net.Console.Record.NETCoreApp/WireMock.Net.Console.Record.NETCoreApp.csproj @@ -0,0 +1,19 @@ + + + + Exe + netcoreapp1.1 + ../../WireMock.Net-Logo.ico + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/WireMock.Net.ConsoleApplication/Program.cs b/examples/WireMock.Net.ConsoleApplication/Program.cs index 68a5fb8f7..93163fb70 100644 --- a/examples/WireMock.Net.ConsoleApplication/Program.cs +++ b/examples/WireMock.Net.ConsoleApplication/Program.cs @@ -5,6 +5,7 @@ using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Server; +using WireMock.Settings; namespace WireMock.Net.ConsoleApplication { diff --git a/src/WireMock.Net.StandAlone.NETCoreApp/Program.cs b/src/WireMock.Net.StandAlone.NETCoreApp/Program.cs index 359322025..ad8355680 100644 --- a/src/WireMock.Net.StandAlone.NETCoreApp/Program.cs +++ b/src/WireMock.Net.StandAlone.NETCoreApp/Program.cs @@ -4,6 +4,7 @@ using CommandLineParser.Arguments; using CommandLineParser.Exceptions; using WireMock.Server; +using WireMock.Settings; namespace WireMock.Net.StandAlone.NETCoreApp { diff --git a/src/WireMock.Net.StandAlone/Program.cs b/src/WireMock.Net.StandAlone/Program.cs index f82109c25..a5bb3d0dd 100644 --- a/src/WireMock.Net.StandAlone/Program.cs +++ b/src/WireMock.Net.StandAlone/Program.cs @@ -4,6 +4,7 @@ using CommandLineParser.Arguments; using CommandLineParser.Exceptions; using WireMock.Server; +using WireMock.Settings; namespace WireMock.Net.StandAlone { diff --git a/src/WireMock.Net/DynamicResponseProvider.cs b/src/WireMock.Net/DynamicResponseProvider.cs index 82ca49f50..acf4848ee 100644 --- a/src/WireMock.Net/DynamicResponseProvider.cs +++ b/src/WireMock.Net/DynamicResponseProvider.cs @@ -2,6 +2,7 @@ using System.Threading.Tasks; using JetBrains.Annotations; using WireMock.Validation; +using WireMock.Settings; namespace WireMock { @@ -21,4 +22,41 @@ public Task ProvideResponseAsync(RequestMessage requestMessage) return Task.FromResult(_responseMessageFunc(requestMessage)); } } + + internal class DynamicAsyncResponseProvider : IResponseProvider + { + private readonly Func> _responseMessageFunc; + + public DynamicAsyncResponseProvider([NotNull] Func> responseMessageFunc) + { + Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); + + _responseMessageFunc = responseMessageFunc; + } + + public Task ProvideResponseAsync(RequestMessage requestMessage) + { + return _responseMessageFunc(requestMessage); + } + } + + internal class ProxyAsyncResponseProvider : IResponseProvider + { + private readonly Func> _responseMessageFunc; + private readonly ProxyAndRecordSettings _settings; + + public ProxyAsyncResponseProvider([NotNull] Func> responseMessageFunc, [NotNull] ProxyAndRecordSettings settings) + { + Check.NotNull(responseMessageFunc, nameof(responseMessageFunc)); + Check.NotNull(settings, nameof(settings)); + + _responseMessageFunc = responseMessageFunc; + _settings = settings; + } + + public Task ProvideResponseAsync(RequestMessage requestMessage) + { + return _responseMessageFunc(requestMessage, _settings); + } + } } \ No newline at end of file diff --git a/src/WireMock.Net/Mapping.cs b/src/WireMock.Net/Mapping.cs index 06c953d41..bebff0e1d 100644 --- a/src/WireMock.Net/Mapping.cs +++ b/src/WireMock.Net/Mapping.cs @@ -91,6 +91,6 @@ public RequestMatchResult IsRequestHandled(RequestMessage requestMessage) /// /// true if this mapping is an Admin Interface; otherwise, false. /// - public bool IsAdminInterface => Provider is DynamicResponseProvider; + public bool IsAdminInterface => Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider || Provider is ProxyAsyncResponseProvider; } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index 2ae852450..1f640f4eb 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -16,6 +16,9 @@ using WireMock.ResponseBuilders; using WireMock.Util; using WireMock.Validation; +using WireMock.Http; +using System.Threading.Tasks; +using WireMock.Settings; namespace WireMock.Server { @@ -117,6 +120,20 @@ private void InitAdmin() Given(Request.Create().WithPath(AdminRequests + "/find").UsingPost()).RespondWith(new DynamicResponseProvider(RequestsFind)); } + private void InitProxyAndRecord(ProxyAndRecordSettings settings) + { + Given(Request.Create().WithPath("/*").UsingAnyVerb()).RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings)); + } + + #region Proxy and Record + private async Task ProxyAndRecordAsync(RequestMessage requestMessage, ProxyAndRecordSettings settings) + { + var responseMessage = await HttpClientHelper.SendAsync(requestMessage, settings.Url); + + return responseMessage; + } + #endregion + #region Settings private ResponseMessage SettingsGet(RequestMessage requestMessage) { diff --git a/src/WireMock.Net/Server/FluentMockServer.cs b/src/WireMock.Net/Server/FluentMockServer.cs index 408f980c3..122e510b2 100644 --- a/src/WireMock.Net/Server/FluentMockServer.cs +++ b/src/WireMock.Net/Server/FluentMockServer.cs @@ -9,6 +9,7 @@ using WireMock.Matchers; using WireMock.Matchers.Request; using WireMock.RequestBuilders; +using WireMock.Settings; using WireMock.Validation; using WireMock.Owin; @@ -181,6 +182,11 @@ private FluentMockServer(FluentMockServerSettings settings) { ReadStaticMappings(); } + + if (settings.ProxyAndRecordSettings != null) + { + InitProxyAndRecord(settings.ProxyAndRecordSettings); + } } /// @@ -235,7 +241,7 @@ public void ResetMappings() { lock (((ICollection)_options.Mappings).SyncRoot) { - _options.Mappings = _options.Mappings.Where(m => m.Provider is DynamicResponseProvider).ToList(); + _options.Mappings = _options.Mappings.Where(m => m.IsAdminInterface).ToList(); } } diff --git a/src/WireMock.Net/Server/IRespondWithAProvider.cs b/src/WireMock.Net/Server/IRespondWithAProvider.cs index 1ee3c5365..652872831 100644 --- a/src/WireMock.Net/Server/IRespondWithAProvider.cs +++ b/src/WireMock.Net/Server/IRespondWithAProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; namespace WireMock.Server { @@ -38,9 +39,13 @@ public interface IRespondWithAProvider /// /// The respond with. /// - /// - /// The provider. - /// + /// The provider. void RespondWith(IResponseProvider provider); + + ///// + ///// The respond with. + ///// + ///// The provider. + //Task RespondWithAsync(IResponseProvider provider); } } \ No newline at end of file diff --git a/src/WireMock.Net/Server/FluentMockServerSettings.cs b/src/WireMock.Net/Settings/FluentMockServerSettings.cs similarity index 75% rename from src/WireMock.Net/Server/FluentMockServerSettings.cs rename to src/WireMock.Net/Settings/FluentMockServerSettings.cs index 9a81eedd3..548af56bd 100644 --- a/src/WireMock.Net/Server/FluentMockServerSettings.cs +++ b/src/WireMock.Net/Settings/FluentMockServerSettings.cs @@ -1,4 +1,4 @@ -namespace WireMock.Server +namespace WireMock.Settings { /// /// FluentMockServerSettings @@ -31,13 +31,17 @@ public class FluentMockServerSettings public bool? StartAdminInterface { get; set; } /// - /// Gets or sets the read static mappings. + /// Gets or sets if the static mappings should be read at startup. /// - /// - /// The read static mappings. - /// + /// true/false public bool? ReadStaticMappings { get; set; } + /// + /// Gets or sets if the server should record and save requests and responses. + /// + /// true/false + public ProxyAndRecordSettings ProxyAndRecordSettings { get; set; } + /// /// Gets or sets the urls. /// diff --git a/src/WireMock.Net/Settings/ProxyAndRecordSettings.cs b/src/WireMock.Net/Settings/ProxyAndRecordSettings.cs new file mode 100644 index 000000000..4d603b8f0 --- /dev/null +++ b/src/WireMock.Net/Settings/ProxyAndRecordSettings.cs @@ -0,0 +1,18 @@ +namespace WireMock.Settings +{ + /// + /// RecordAndSaveSettings + /// + public class ProxyAndRecordSettings + { + /// + /// The URL to proxy. + /// + public string Url { get; set; } + + /// + /// Save the mapping for each request/response. + /// + public bool SaveMapping { get; set; } = true; + } +} \ No newline at end of file