Support Dynamic response files using Handlebars templating (#271)

* Dynamic response files using Handlebars templating
(#270)

* * Response templating / transformation using Handlebars and extensions
This commit is contained in:
Stef Heyenrath
2019-05-04 10:02:09 +02:00
committed by GitHub
parent b151a581cc
commit 96e68ae2a0
6 changed files with 56 additions and 26 deletions

View File

@@ -4,7 +4,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<VersionPrefix>1.0.14</VersionPrefix> <VersionPrefix>1.0.15</VersionPrefix>
</PropertyGroup> </PropertyGroup>
<Choose> <Choose>

View File

@@ -8,7 +8,7 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w
* Record/playback of stubs (proxying) * Record/playback of stubs (proxying)
* Per-request conditional proxying * Per-request conditional proxying
* Stateful behaviour simulation * Stateful behaviour simulation
* Response transformation * Response templating / transformation using Handlebars and extensions
## Info ## Info
| | | | | |

View File

@@ -224,7 +224,7 @@ namespace WireMock.ResponseBuilders
BodyAsFileIsCached = cache BodyAsFileIsCached = cache
}; };
if (cache) if (cache && !UseTransformer)
{ {
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes; ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
ResponseMessage.BodyData.BodyAsBytes = _fileSystemHandler.ReadResponseBodyAsFile(filename); ResponseMessage.BodyData.BodyAsBytes = _fileSystemHandler.ReadResponseBodyAsFile(filename);

View File

@@ -722,6 +722,11 @@ namespace WireMock.Server
responseBuilder = responseBuilder.WithDelay(responseModel.Delay.Value); responseBuilder = responseBuilder.WithDelay(responseModel.Delay.Value);
} }
if (responseModel.UseTransformer)
{
responseBuilder = responseBuilder.WithTransformer();
}
if (!string.IsNullOrEmpty(responseModel.ProxyUrl)) if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
{ {
if (string.IsNullOrEmpty(responseModel.X509Certificate2ThumbprintOrSubjectName)) if (string.IsNullOrEmpty(responseModel.X509Certificate2ThumbprintOrSubjectName))
@@ -778,11 +783,6 @@ namespace WireMock.Server
responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile); responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
} }
if (responseModel.UseTransformer)
{
responseBuilder = responseBuilder.WithTransformer();
}
return responseBuilder; return responseBuilder;
} }

View File

@@ -1,9 +1,9 @@
using System; using HandlebarsDotNet;
using System.Collections.Generic;
using System.Linq;
using HandlebarsDotNet;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using WireMock.Util; using WireMock.Util;
namespace WireMock.Transformers namespace WireMock.Transformers
@@ -24,23 +24,24 @@ namespace WireMock.Transformers
public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original) public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
{ {
bool bodyIsJson = original.BodyData.DetectedBodyType == BodyType.Json;
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode }; var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
if (!bodyIsJson)
{
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
}
var template = new { request = requestMessage }; var template = new { request = requestMessage };
if (!bodyIsJson) switch (original.BodyData.DetectedBodyType)
{ {
TransformBodyAsString(template, original, responseMessage); case BodyType.Json:
} TransformBodyAsJson(template, original, responseMessage);
else break;
{
TransformBodyAsJson(template, original, responseMessage); case BodyType.File:
TransformBodyAsFile(template, original, responseMessage);
break;
case BodyType.String:
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
TransformBodyAsString(template, original, responseMessage);
break;
} }
// Headers // Headers
@@ -150,13 +151,25 @@ namespace WireMock.Transformers
private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage) private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage)
{ {
var templateBody = HandlebarsContext.Compile(original.BodyData.BodyAsString); var templateBodyAsString = HandlebarsContext.Compile(original.BodyData.BodyAsString);
responseMessage.BodyData = new BodyData responseMessage.BodyData = new BodyData
{ {
DetectedBodyType = original.BodyData.DetectedBodyType, DetectedBodyType = original.BodyData.DetectedBodyType,
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
BodyAsString = templateBody(template) BodyAsString = templateBodyAsString(template)
};
}
private static void TransformBodyAsFile(object template, ResponseMessage original, ResponseMessage responseMessage)
{
var templateBodyAsFile = HandlebarsContext.Compile(original.BodyData.BodyAsFile);
responseMessage.BodyData = new BodyData
{
DetectedBodyType = original.BodyData.DetectedBodyType,
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
BodyAsFile = templateBodyAsFile(template)
}; };
} }
} }

View File

@@ -214,5 +214,22 @@ namespace WireMock.Net.Tests.ResponseBuilders
// Assert // Assert
Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]"); Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]");
} }
[Fact]
public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile()
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost/foo?MyUniqueNumber=1"), "GET", ClientIp);
var response = Response.Create()
.WithTransformer()
.WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\test.xml"); // why use a \\ here ?
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
}
} }
} }