Handlebars Extension (#286)

* wip

* HandlebarsRegistrationCallback

* HandlebarsContextFactoryTests

* 1.0.21.0

* fix sonar

* LocalFileSystemHandler

* readme

* Fix System.IO.IOException
This commit is contained in:
Stef Heyenrath
2019-07-03 18:37:22 +02:00
committed by GitHub
parent 653e03fcd9
commit 93682c9bbf
37 changed files with 366 additions and 208 deletions

View File

@@ -11,6 +11,24 @@ namespace WireMock.Handlers
{
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
private readonly string _rootFolder;
/// <summary>
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
/// </summary>
public LocalFileSystemHandler() : this(Directory.GetCurrentDirectory())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
/// </summary>
/// <param name="rootFolder">The root folder.</param>
public LocalFileSystemHandler(string rootFolder)
{
_rootFolder = rootFolder;
}
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
public bool FolderExists(string path)
{
@@ -38,7 +56,7 @@ namespace WireMock.Handlers
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
public string GetMappingFolder()
{
return Path.Combine(Directory.GetCurrentDirectory(), AdminMappingsFolder);
return Path.Combine(_rootFolder, AdminMappingsFolder);
}
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>

View File

@@ -1,9 +1,9 @@
using JetBrains.Annotations;
using System;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Matchers.Request;
using WireMock.ResponseProviders;
using WireMock.Settings;
namespace WireMock
{
@@ -62,9 +62,9 @@ namespace WireMock
IResponseProvider Provider { get; }
/// <summary>
/// The FileSystemHandler.
/// The FluentMockServerSettings.
/// </summary>
IFileSystemHandler FileSystemHandler { get; }
IFluentMockServerSettings Settings { get; }
/// <summary>
/// Is State started ?

View File

@@ -1,9 +1,9 @@
using JetBrains.Annotations;
using System;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Matchers.Request;
using WireMock.ResponseProviders;
using WireMock.Settings;
namespace WireMock
{
@@ -39,8 +39,8 @@ namespace WireMock
/// <inheritdoc cref="IMapping.Provider" />
public IResponseProvider Provider { get; }
/// <inheritdoc cref="IMapping.FileSystemHandler" />
public IFileSystemHandler FileSystemHandler { get; }
/// <inheritdoc cref="IMapping.Settings" />
public IFluentMockServerSettings Settings { get; }
/// <inheritdoc cref="IMapping.IsStartState" />
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
@@ -54,7 +54,7 @@ namespace WireMock
/// <param name="guid">The unique identifier.</param>
/// <param name="title">The unique title (can be null).</param>
/// <param name="path">The full file path from this mapping title (can be null).</param>
/// <param name="fileSystemHandler">The fileSystemHandler.</param>
/// <param name="settings">The FluentMockServerSettings.</param>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="provider">The provider.</param>
/// <param name="priority">The priority for this mapping.</param>
@@ -62,13 +62,13 @@ namespace WireMock
/// <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>
public Mapping(Guid guid, [CanBeNull] string title, [CanBeNull] string path,
[NotNull] IFileSystemHandler fileSystemHandler, [NotNull] IRequestMatcher requestMatcher, [NotNull] IResponseProvider provider,
[NotNull] IFluentMockServerSettings settings, [NotNull] IRequestMatcher requestMatcher, [NotNull] IResponseProvider provider,
int priority, [CanBeNull] string scenario, [CanBeNull] string executionConditionState, [CanBeNull] string nextState)
{
Guid = guid;
Title = title;
Path = path;
FileSystemHandler = fileSystemHandler;
Settings = settings;
RequestMatcher = requestMatcher;
Provider = provider;
Priority = priority;
@@ -80,7 +80,7 @@ namespace WireMock
/// <inheritdoc cref="IMapping.ResponseToAsync" />
public async Task<ResponseMessage> ResponseToAsync(RequestMessage requestMessage)
{
return await Provider.ProvideResponseAsync(requestMessage, FileSystemHandler);
return await Provider.ProvideResponseAsync(requestMessage, Settings);
}
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />

View File

@@ -10,8 +10,14 @@ namespace WireMock.Matchers
/// <seealso cref="IObjectMatcher" />
public class ExactObjectMatcher : IObjectMatcher
{
/// <summary>
/// Gets the value as object.
/// </summary>
public object ValueAsObject { get; }
/// <summary>
/// Gets the value as byte[].
/// </summary>
public byte[] ValueAsBytes { get; }
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>

View File

@@ -63,6 +63,7 @@ namespace WireMock.RequestBuilders
return this;
}
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, MatchBehaviour, IStringMatcher[])"/>
public IRequestBuilder WithParam(string key, MatchBehaviour matchBehaviour, params IStringMatcher[] matchers)
{
return WithParam(key, matchBehaviour, false, matchers);
@@ -77,7 +78,7 @@ namespace WireMock.RequestBuilders
return this;
}
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{T}}, bool}[])"/>
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{string}}, bool}[])"/>
public IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs)
{
Check.NotNullOrEmpty(funcs, nameof(funcs));

View File

@@ -7,8 +7,8 @@ using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Http;
using WireMock.ResponseProviders;
using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Util;
@@ -371,7 +371,8 @@ namespace WireMock.ResponseBuilders
return this;
}
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFileSystemHandler fileSystemHandler)
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, IFluentMockServerSettings)"/>
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
{
Check.NotNull(requestMessage, nameof(requestMessage));
@@ -410,13 +411,14 @@ namespace WireMock.ResponseBuilders
if (UseTransformer)
{
var responseMessageTransformer = new ResponseMessageTransformer(fileSystemHandler);
var factory = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback);
var responseMessageTransformer = new ResponseMessageTransformer(factory);
return responseMessageTransformer.Transform(requestMessage, ResponseMessage);
}
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
{
ResponseMessage.BodyData.BodyAsBytes = fileSystemHandler.ReadResponseBodyAsFile(ResponseMessage.BodyData.BodyAsFile);
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(ResponseMessage.BodyData.BodyAsFile);
ResponseMessage.BodyData.BodyAsFile = null;
}

View File

@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Settings;
namespace WireMock.ResponseProviders
{
@@ -13,7 +13,7 @@ namespace WireMock.ResponseProviders
_responseMessageFunc = responseMessageFunc;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFileSystemHandler fileSystemHandler)
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
{
return _responseMessageFunc(requestMessage);
}

View File

@@ -1,6 +1,6 @@
using System;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Settings;
namespace WireMock.ResponseProviders
{
@@ -13,7 +13,7 @@ namespace WireMock.ResponseProviders
_responseMessageFunc = responseMessageFunc;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFileSystemHandler fileSystemHandler)
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
{
return Task.FromResult(_responseMessageFunc(requestMessage));
}

View File

@@ -1,6 +1,6 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Handlers;
using JetBrains.Annotations;
using System.Threading.Tasks;
using WireMock.Settings;
namespace WireMock.ResponseProviders
{
@@ -13,8 +13,8 @@ namespace WireMock.ResponseProviders
/// The provide response.
/// </summary>
/// <param name="requestMessage">The request.</param>
/// <param name="fileSystemHandler">The fileSystemHandler.</param>
/// <param name="settings">The FluentMockServerSettings.</param>
/// <returns>The <see cref="ResponseMessage"/>.</returns>
Task<ResponseMessage> ProvideResponseAsync([NotNull] RequestMessage requestMessage, [NotNull] IFileSystemHandler fileSystemHandler);
Task<ResponseMessage> ProvideResponseAsync([NotNull] RequestMessage requestMessage, [NotNull] IFluentMockServerSettings settings);
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using WireMock.Handlers;
using WireMock.Settings;
namespace WireMock.ResponseProviders
@@ -16,7 +15,7 @@ namespace WireMock.ResponseProviders
_settings = settings;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFileSystemHandler fileSystemHandler)
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IFluentMockServerSettings settings)
{
return _responseMessageFunc(requestMessage, _settings);
}

View File

@@ -164,10 +164,10 @@ namespace WireMock.Server
{
if (folder == null)
{
folder = _fileSystemHandler.GetMappingFolder();
folder = _settings.FileSystemHandler.GetMappingFolder();
}
if (!_fileSystemHandler.FolderExists(folder))
if (!_settings.FileSystemHandler.FolderExists(folder))
{
return;
}
@@ -177,17 +177,23 @@ namespace WireMock.Server
var watcher = new EnhancedFileSystemWatcher(folder, "*.json", EnhancedFileSystemWatcherTimeoutMs);
watcher.Created += (sender, args) =>
{
_logger.Info("New MappingFile created : '{0}'", args.FullPath);
ReadStaticMappingAndAddOrUpdate(args.FullPath);
_logger.Info("MappingFile created : '{0}', reading file.", args.FullPath);
if (!ReadStaticMappingAndAddOrUpdate(args.FullPath))
{
_logger.Error("Unable to read MappingFile '{0}'.", args.FullPath);
}
};
watcher.Changed += (sender, args) =>
{
_logger.Info("New MappingFile updated : '{0}'", args.FullPath);
ReadStaticMappingAndAddOrUpdate(args.FullPath);
_logger.Info("MappingFile updated : '{0}', reading file.", args.FullPath);
if (!ReadStaticMappingAndAddOrUpdate(args.FullPath))
{
_logger.Error("Unable to read MappingFile '{0}'.", args.FullPath);
}
};
watcher.Deleted += (sender, args) =>
{
_logger.Info("New MappingFile deleted : '{0}'", args.FullPath);
_logger.Info("MappingFile deleted : '{0}'", args.FullPath);
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
@@ -208,24 +214,31 @@ namespace WireMock.Server
/// </summary>
/// <param name="path">The path.</param>
[PublicAPI]
public void ReadStaticMappingAndAddOrUpdate([NotNull] string path)
public bool ReadStaticMappingAndAddOrUpdate([NotNull] string path)
{
Check.NotNull(path, nameof(path));
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
var mappingModels = DeserializeObjectToArray<MappingModel>(JsonConvert.DeserializeObject(_fileSystemHandler.ReadMappingFile(path)));
foreach (var mappingModel in mappingModels)
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_fileSystemHandler, path, out string value))
{
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
var mappingModels = DeserializeObjectToArray<MappingModel>(JsonConvert.DeserializeObject(value));
foreach (var mappingModel in mappingModels)
{
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
}
else
{
DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
{
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
}
else
{
DeserializeAndAddOrUpdateMapping(mappingModel, null, path);
}
}
return true;
}
return false;
}
#endregion
@@ -302,7 +315,7 @@ namespace WireMock.Server
var response = Response.Create(responseMessage);
return new Mapping(Guid.NewGuid(), string.Empty, null, _fileSystemHandler, request, response, 0, null, null, null);
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null);
}
#endregion

View File

@@ -29,6 +29,7 @@ namespace WireMock.Server
private readonly IWireMockLogger _logger;
private readonly IFileSystemHandler _fileSystemHandler;
private readonly IFluentMockServerSettings _settings;
private readonly IOwinSelfHost _httpServer;
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
@@ -92,7 +93,7 @@ namespace WireMock.Server
/// <param name="settings">The FluentMockServerSettings.</param>
/// <returns>The <see cref="FluentMockServer"/>.</returns>
[PublicAPI]
public static FluentMockServer Start(IFluentMockServerSettings settings)
public static FluentMockServer Start([NotNull] IFluentMockServerSettings settings)
{
Check.NotNull(settings, nameof(settings));
@@ -185,6 +186,7 @@ namespace WireMock.Server
private FluentMockServer(IFluentMockServerSettings settings)
{
_settings = settings;
settings.Logger = settings.Logger ?? new WireMockNullLogger();
_logger = settings.Logger;
@@ -435,7 +437,7 @@ namespace WireMock.Server
[PublicAPI]
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
{
return new RespondWithAProvider(RegisterMapping, requestMatcher, _fileSystemHandler, saveToFile);
return new RespondWithAProvider(RegisterMapping, requestMatcher, _settings, saveToFile);
}
private void RegisterMapping(IMapping mapping, bool saveToFile)

View File

@@ -1,7 +1,7 @@
using System;
using WireMock.Handlers;
using WireMock.Matchers.Request;
using WireMock.ResponseProviders;
using WireMock.Settings;
namespace WireMock.Server
{
@@ -18,7 +18,7 @@ namespace WireMock.Server
private string _scenario;
private readonly RegistrationCallback _registrationCallback;
private readonly IRequestMatcher _requestMatcher;
private readonly IFileSystemHandler _fileSystemHandler;
private readonly IFluentMockServerSettings _settings;
private readonly bool _saveToFile;
public Guid Guid { get; private set; } = Guid.NewGuid();
@@ -28,13 +28,13 @@ namespace WireMock.Server
/// </summary>
/// <param name="registrationCallback">The registration callback.</param>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="fileSystemHandler">The fileSystemHandler.</param>
/// <param name="settings">The FluentMockServerSettings.</param>
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher, IFileSystemHandler fileSystemHandler, bool saveToFile = false)
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher, IFluentMockServerSettings settings, bool saveToFile = false)
{
_registrationCallback = registrationCallback;
_requestMatcher = requestMatcher;
_fileSystemHandler = fileSystemHandler;
_settings = settings;
_saveToFile = saveToFile;
}
@@ -44,7 +44,7 @@ namespace WireMock.Server
/// <param name="provider">The provider.</param>
public void RespondWith(IResponseProvider provider)
{
_registrationCallback(new Mapping(Guid, _title, _path, _fileSystemHandler, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState), _saveToFile);
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState), _saveToFile);
}
/// <see cref="IRespondWithAProvider.WithGuid(string)"/>

View File

@@ -1,4 +1,5 @@
using JetBrains.Annotations;
using HandlebarsDotNet;
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using WireMock.Handlers;
@@ -83,5 +84,10 @@ namespace WireMock.Settings
[PublicAPI]
[JsonIgnore]
public IFileSystemHandler FileSystemHandler { get; set; }
/// <inheritdoc cref="IFluentMockServerSettings.HandlebarsRegistrationCallback"/>
[PublicAPI]
[JsonIgnore]
public Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
}
}

View File

@@ -1,5 +1,6 @@
using System;
using HandlebarsDotNet;
using JetBrains.Annotations;
using System;
using WireMock.Handlers;
using WireMock.Logging;
@@ -112,5 +113,11 @@ namespace WireMock.Settings
/// </summary>
[PublicAPI]
IFileSystemHandler FileSystemHandler { get; set; }
/// <summary>
/// Action which can be used to add additional is Handlebar registrations. [Optional]
/// </summary>
[PublicAPI]
Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
}
}

View File

@@ -0,0 +1,34 @@
using HandlebarsDotNet;
using System;
using WireMock.Handlers;
namespace WireMock.Transformers
{
internal class HandlebarsContextFactory : IHandlebarsContextFactory
{
private static readonly HandlebarsConfiguration HandlebarsConfiguration = new HandlebarsConfiguration
{
UnresolvedBindingFormatter = "{0}"
};
private readonly IFileSystemHandler _fileSystemHandler;
private readonly Action<IHandlebars, IFileSystemHandler> _action;
public HandlebarsContextFactory(IFileSystemHandler fileSystemHandler, Action<IHandlebars, IFileSystemHandler> action)
{
_fileSystemHandler = fileSystemHandler;
_action = action;
}
public IHandlebars Create()
{
var handlebarsContext = Handlebars.Create(HandlebarsConfiguration);
HandlebarsHelpers.Register(handlebarsContext, _fileSystemHandler);
_action?.Invoke(handlebarsContext, _fileSystemHandler);
return handlebarsContext;
}
}
}

View File

@@ -0,0 +1,9 @@
using HandlebarsDotNet;
namespace WireMock.Transformers
{
interface IHandlebarsContextFactory
{
IHandlebars Create();
}
}

View File

@@ -5,7 +5,6 @@ using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using WireMock.Handlers;
using WireMock.Util;
using WireMock.Validation;
@@ -13,22 +12,19 @@ namespace WireMock.Transformers
{
internal class ResponseMessageTransformer
{
private static readonly HandlebarsConfiguration HandlebarsConfiguration = new HandlebarsConfiguration
private readonly IHandlebarsContextFactory _factory;
public ResponseMessageTransformer([NotNull] IHandlebarsContextFactory factory)
{
UnresolvedBindingFormatter = "{0}"
};
Check.NotNull(factory, nameof(factory));
private static readonly IHandlebars HandlebarsContext = Handlebars.Create(HandlebarsConfiguration);
public ResponseMessageTransformer([NotNull] IFileSystemHandler fileSystemHandler)
{
Check.NotNull(fileSystemHandler, nameof(fileSystemHandler));
HandlebarsHelpers.Register(HandlebarsContext, fileSystemHandler);
_factory = factory;
}
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
{
var handlebarsContext = _factory.Create();
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
var template = new { request = requestMessage };
@@ -36,16 +32,16 @@ namespace WireMock.Transformers
switch (original.BodyData.DetectedBodyType)
{
case BodyType.Json:
TransformBodyAsJson(template, original, responseMessage);
TransformBodyAsJson(handlebarsContext, template, original, responseMessage);
break;
case BodyType.File:
TransformBodyAsFile(template, original, responseMessage);
TransformBodyAsFile(handlebarsContext, template, original, responseMessage);
break;
case BodyType.String:
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
TransformBodyAsString(template, original, responseMessage);
TransformBodyAsString(handlebarsContext, template, original, responseMessage);
break;
}
@@ -53,9 +49,9 @@ namespace WireMock.Transformers
var newHeaders = new Dictionary<string, WireMockList<string>>();
foreach (var header in original.Headers)
{
var templateHeaderKey = HandlebarsContext.Compile(header.Key);
var templateHeaderKey = handlebarsContext.Compile(header.Key);
var templateHeaderValues = header.Value
.Select(HandlebarsContext.Compile)
.Select(handlebarsContext.Compile)
.Select(func => func(template))
.ToArray();
@@ -67,7 +63,7 @@ namespace WireMock.Transformers
return responseMessage;
}
private static void TransformBodyAsJson(object template, ResponseMessage original, ResponseMessage responseMessage)
private static void TransformBodyAsJson(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
{
JToken jToken;
switch (original.BodyData.BodyAsJson)
@@ -85,7 +81,7 @@ namespace WireMock.Transformers
break;
}
WalkNode(jToken, template);
WalkNode(handlebarsContext, jToken, template);
responseMessage.BodyData = new BodyData
{
@@ -95,14 +91,14 @@ namespace WireMock.Transformers
};
}
private static void WalkNode(JToken node, object context)
private static void WalkNode(IHandlebars handlebarsContext, JToken node, object context)
{
if (node.Type == JTokenType.Object)
{
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JProperty child in node.Children<JProperty>().ToArray())
{
WalkNode(child.Value, context);
WalkNode(handlebarsContext, child.Value, context);
}
}
else if (node.Type == JTokenType.Array)
@@ -110,7 +106,7 @@ namespace WireMock.Transformers
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JToken child in node.Children().ToArray())
{
WalkNode(child, context);
WalkNode(handlebarsContext, child, context);
}
}
else if (node.Type == JTokenType.String)
@@ -122,7 +118,7 @@ namespace WireMock.Transformers
return;
}
var templateForStringValue = HandlebarsContext.Compile(stringValue);
var templateForStringValue = handlebarsContext.Compile(stringValue);
string transformedString = templateForStringValue(context);
if (!string.Equals(stringValue, transformedString))
{
@@ -154,9 +150,9 @@ namespace WireMock.Transformers
node.Replace(value);
}
private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage)
private static void TransformBodyAsString(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
{
var templateBodyAsString = HandlebarsContext.Compile(original.BodyData.BodyAsString);
var templateBodyAsString = handlebarsContext.Compile(original.BodyData.BodyAsString);
responseMessage.BodyData = new BodyData
{
@@ -166,9 +162,9 @@ namespace WireMock.Transformers
};
}
private static void TransformBodyAsFile(object template, ResponseMessage original, ResponseMessage responseMessage)
private static void TransformBodyAsFile(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
{
var templateBodyAsFile = HandlebarsContext.Compile(original.BodyData.BodyAsFile);
var templateBodyAsFile = handlebarsContext.Compile(original.BodyData.BodyAsFile);
responseMessage.BodyData = new BodyData
{

View File

@@ -1,6 +1,5 @@
using System.IO;
using JetBrains.Annotations;
using System.Threading;
using JetBrains.Annotations;
using WireMock.Handlers;
using WireMock.Validation;
@@ -11,16 +10,19 @@ namespace WireMock.Util
private const int NumberOfRetries = 3;
private const int DelayOnRetry = 500;
public static string ReadAllTextWithRetryAndDelay([NotNull] IFileSystemHandler handler, [NotNull] string path)
public static bool TryReadMappingFileWithRetryAndDelay([NotNull] IFileSystemHandler handler, [NotNull] string path, out string value)
{
Check.NotNull(handler, nameof(handler));
Check.NotNullOrEmpty(path, nameof(path));
value = null;
for (int i = 1; i <= NumberOfRetries; ++i)
{
try
{
return handler.ReadMappingFile(path);
value = handler.ReadMappingFile(path);
return true;
}
catch
{
@@ -28,7 +30,7 @@ namespace WireMock.Util
}
}
throw new IOException();
return false;
}
}
}