diff --git a/examples/WireMock.Net.Console.NETCoreApp2/__admin/mappings/1.cs b/examples/WireMock.Net.Console.NETCoreApp2/__admin/mappings/1.cs index 3310d6a23..c8143e099 100644 --- a/examples/WireMock.Net.Console.NETCoreApp2/__admin/mappings/1.cs +++ b/examples/WireMock.Net.Console.NETCoreApp2/__admin/mappings/1.cs @@ -1 +1 @@ -C# Hello \ No newline at end of file +// C# Hello \ No newline at end of file diff --git a/src/WireMock.Net/Admin/Mappings/ResponseModel.cs b/src/WireMock.Net/Admin/Mappings/ResponseModel.cs index d7725263d..158624f46 100644 --- a/src/WireMock.Net/Admin/Mappings/ResponseModel.cs +++ b/src/WireMock.Net/Admin/Mappings/ResponseModel.cs @@ -62,6 +62,11 @@ public class ResponseModel /// public bool? UseTransformer { get; set; } + /// + /// Use the Handlerbars transformer for the content from the referenced BodyAsFile. + /// + public bool? UseTransformerForBodyAsFile { get; set; } + /// /// Gets or sets the headers. /// diff --git a/src/WireMock.Net/ResponseBuilders/ITransformResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/ITransformResponseBuilder.cs index 11af07f24..1efb2e411 100644 --- a/src/WireMock.Net/ResponseBuilders/ITransformResponseBuilder.cs +++ b/src/WireMock.Net/ResponseBuilders/ITransformResponseBuilder.cs @@ -11,6 +11,6 @@ public interface ITransformResponseBuilder : IDelayResponseBuilder /// /// The . /// - IResponseBuilder WithTransformer(); + IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile = false); } } \ No newline at end of file diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 7b703bf1a..8d042251d 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -33,6 +33,11 @@ public partial class Response : IResponseBuilder /// public bool UseTransformer { get; private set; } + /// + /// Gets a value indicating whether to use the Handlerbars transformer for the content from the referenced BodyAsFile. + /// + public bool UseTransformerForBodyAsFile { get; private set; } + /// /// The Proxy URL to use. /// @@ -311,10 +316,11 @@ public IResponseBuilder WithBodyFromBase64(string bodyAsBase64, Encoding encodin return this; } - /// - public IResponseBuilder WithTransformer() + /// + public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile = false) { UseTransformer = true; + UseTransformerForBodyAsFile = transformContentFromBodyAsFile; return this; } @@ -414,7 +420,7 @@ public async Task ProvideResponseAsync(RequestMessage requestMe { var factory = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback); var responseMessageTransformer = new ResponseMessageTransformer(factory); - return responseMessageTransformer.Transform(requestMessage, ResponseMessage); + return responseMessageTransformer.Transform(requestMessage, ResponseMessage, UseTransformerForBodyAsFile); } if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true) diff --git a/src/WireMock.Net/Serialization/MappingConverter.cs b/src/WireMock.Net/Serialization/MappingConverter.cs index ae6ee3544..144ecc67c 100644 --- a/src/WireMock.Net/Serialization/MappingConverter.cs +++ b/src/WireMock.Net/Serialization/MappingConverter.cs @@ -112,6 +112,7 @@ public MappingModel ToMappingModel(IMapping mapping) mappingModel.Response.BodyAsFile = null; mappingModel.Response.BodyAsFileIsCached = null; mappingModel.Response.UseTransformer = null; + mappingModel.Response.UseTransformerForBodyAsFile = null; mappingModel.Response.BodyEncoding = null; mappingModel.Response.ProxyUrl = response.ProxyUrl; mappingModel.Response.Fault = null; @@ -125,6 +126,10 @@ public MappingModel ToMappingModel(IMapping mapping) { mappingModel.Response.UseTransformer = response.UseTransformer; } + if (response.UseTransformerForBodyAsFile) + { + mappingModel.Response.UseTransformerForBodyAsFile = response.UseTransformerForBodyAsFile; + } if (response.ResponseMessage.BodyData != null) { diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs index c83d108d4..239006f39 100644 --- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs +++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs @@ -785,7 +785,7 @@ private IResponseBuilder InitResponseBuilder(ResponseModel responseModel) if (responseModel.UseTransformer == true) { - responseBuilder = responseBuilder.WithTransformer(); + responseBuilder = responseBuilder.WithTransformer(responseModel.UseTransformerForBodyAsFile == true); } if (!string.IsNullOrEmpty(responseModel.ProxyUrl)) diff --git a/src/WireMock.Net/Transformers/HandlebarsContext.cs b/src/WireMock.Net/Transformers/HandlebarsContext.cs new file mode 100644 index 000000000..d0187ebe7 --- /dev/null +++ b/src/WireMock.Net/Transformers/HandlebarsContext.cs @@ -0,0 +1,11 @@ +using HandlebarsDotNet; +using WireMock.Handlers; + +namespace WireMock.Transformers +{ + internal class HandlebarsContext : IHandlebarsContext + { + public IHandlebars Handlebars { get; set; } + public IFileSystemHandler FileSystemHandler { get; set; } + } +} \ No newline at end of file diff --git a/src/WireMock.Net/Transformers/HandlebarsContextFactory.cs b/src/WireMock.Net/Transformers/HandlebarsContextFactory.cs index 9993f7fd2..40354e548 100644 --- a/src/WireMock.Net/Transformers/HandlebarsContextFactory.cs +++ b/src/WireMock.Net/Transformers/HandlebarsContextFactory.cs @@ -20,15 +20,19 @@ public HandlebarsContextFactory(IFileSystemHandler fileSystemHandler, Action>(); foreach (var header in original.Headers) { - var templateHeaderKey = handlebarsContext.Compile(header.Key); + var templateHeaderKey = handlebarsContext.Handlebars.Compile(header.Key); var templateHeaderValues = header.Value - .Select(handlebarsContext.Compile) + .Select(handlebarsContext.Handlebars.Compile) .Select(func => func(template)) .ToArray(); @@ -66,7 +65,7 @@ public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage return responseMessage; } - private static void TransformBodyAsJson(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage) + private static void TransformBodyAsJson(IHandlebarsContext handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage) { JToken jToken; switch (original.BodyData.BodyAsJson) @@ -94,7 +93,7 @@ private static void TransformBodyAsJson(IHandlebars handlebarsContext, object te }; } - private static void WalkNode(IHandlebars handlebarsContext, JToken node, object context) + private static void WalkNode(IHandlebarsContext handlebarsContext, JToken node, object context) { if (node.Type == JTokenType.Object) { @@ -121,7 +120,7 @@ private static void WalkNode(IHandlebars handlebarsContext, JToken node, object return; } - var templateForStringValue = handlebarsContext.Compile(stringValue); + var templateForStringValue = handlebarsContext.Handlebars.Compile(stringValue); string transformedString = templateForStringValue(context); if (!string.Equals(stringValue, transformedString)) { @@ -153,9 +152,9 @@ private static void ReplaceNodeValue(JToken node, string stringValue) node.Replace(value); } - private static void TransformBodyAsString(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage) + private static void TransformBodyAsString(IHandlebarsContext handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage) { - var templateBodyAsString = handlebarsContext.Compile(original.BodyData.BodyAsString); + var templateBodyAsString = handlebarsContext.Handlebars.Compile(original.BodyData.BodyAsString); responseMessage.BodyData = new BodyData { @@ -165,16 +164,33 @@ private static void TransformBodyAsString(IHandlebars handlebarsContext, object }; } - private static void TransformBodyAsFile(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage) + private void TransformBodyAsFile(IHandlebarsContext handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage, bool useTransformerForBodyAsFile) { - var templateBodyAsFile = handlebarsContext.Compile(original.BodyData.BodyAsFile); + var templateBodyAsFile = handlebarsContext.Handlebars.Compile(original.BodyData.BodyAsFile); + string transformedBodyAsFilename = templateBodyAsFile(template); - responseMessage.BodyData = new BodyData + if (!useTransformerForBodyAsFile) { - DetectedBodyType = original.BodyData.DetectedBodyType, - DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, - BodyAsFile = templateBodyAsFile(template) - }; + responseMessage.BodyData = new BodyData + { + DetectedBodyType = original.BodyData.DetectedBodyType, + DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, + BodyAsFile = transformedBodyAsFilename + }; + } + else + { + string text = handlebarsContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename); + var templateBodyAsString = handlebarsContext.Handlebars.Compile(text); + + responseMessage.BodyData = new BodyData + { + DetectedBodyType = BodyType.String, + DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, + BodyAsString = templateBodyAsString(template), + BodyAsFile = transformedBodyAsFilename + }; + } } } -} +} \ No newline at end of file diff --git a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs index 516b2de3b..594664c89 100644 --- a/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs +++ b/test/WireMock.Net.Tests/ResponseBuilders/ResponseWithHandlebarsTests.cs @@ -5,6 +5,7 @@ using Moq; using Newtonsoft.Json; using NFluent; +using WireMock.Handlers; using WireMock.Models; using WireMock.ResponseBuilders; using WireMock.Settings; @@ -226,7 +227,7 @@ public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile() var response = Response.Create() .WithTransformer() - .WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\test.xml"); // why use a \\ here ? + .WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\\test.xml"); // Act var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object); @@ -235,6 +236,30 @@ public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile() Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.xml"); } + [Fact] + public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile_And_TransformContentFromBodyAsFile() + { + // Assign + var filesystemHandlerMock = new Mock(MockBehavior.Strict); + filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny())).Returns(""); + + _settingsMock.SetupGet(s => s.FileSystemHandler).Returns(filesystemHandlerMock.Object); + + var request = new RequestMessage(new UrlDetails("http://localhost/foo?MyUniqueNumber=1"), "GET", ClientIp); + + var response = Response.Create() + .WithTransformer(true) + .WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\\test.xml"); + + // Act + var responseMessage = await response.ProvideResponseAsync(request, _settingsMock.Object); + + // Assert + Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.xml"); + Check.That(responseMessage.BodyData.DetectedBodyType).Equals(BodyType.String); + Check.That(responseMessage.BodyData.BodyAsString).Equals(""); + } + [Fact] public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile_JsonPath() {