diff --git a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj
index 06f30ea5f..451f9c483 100644
--- a/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj
+++ b/src/WireMock.Net.StandAlone/WireMock.Net.StandAlone.csproj
@@ -3,7 +3,8 @@
Lightweight StandAlone Http Mocking Server for .Net.
WireMock.Net.StandAlone
Stef Heyenrath
- net451;net452;net46;netstandard1.3;netstandard2.0
+
+ net451;net452;net46;net461;netstandard1.3;netstandard2.0
true
WireMock.Net.StandAlone
WireMock.Net.StandAlone
diff --git a/src/WireMock.Net/Admin/Mappings/ResponseModel.cs b/src/WireMock.Net/Admin/Mappings/ResponseModel.cs
index 78ea85aab..e9c831b48 100644
--- a/src/WireMock.Net/Admin/Mappings/ResponseModel.cs
+++ b/src/WireMock.Net/Admin/Mappings/ResponseModel.cs
@@ -10,7 +10,7 @@ public class ResponseModel
///
/// Gets or sets the HTTP status.
///
- public int? StatusCode { get; set; }
+ public object StatusCode { get; set; }
///
/// Gets or sets the body destination (SameAsSource, String or Bytes).
diff --git a/src/WireMock.Net/Admin/Requests/LogResponseModel.cs b/src/WireMock.Net/Admin/Requests/LogResponseModel.cs
index 8a0aeb222..3986ee56d 100644
--- a/src/WireMock.Net/Admin/Requests/LogResponseModel.cs
+++ b/src/WireMock.Net/Admin/Requests/LogResponseModel.cs
@@ -12,7 +12,7 @@ public class LogResponseModel
///
/// Gets or sets the status code.
///
- public int StatusCode { get; set; } = 200;
+ public object StatusCode { get; set; } = 200;
///
/// Gets the headers.
diff --git a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
index 800a3e5f3..a19353e3b 100644
--- a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
+++ b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
@@ -79,7 +79,17 @@ public async Task MapAsync(ResponseMessage responseMessage, IResponse response)
break;
}
- response.StatusCode = responseMessage.StatusCode;
+ switch (responseMessage.StatusCode)
+ {
+ case int statusCodeAsInteger:
+ response.StatusCode = statusCodeAsInteger;
+ break;
+
+ case string statusCodeAsString:
+ response.StatusCode = int.Parse(statusCodeAsString);
+ break;
+ }
+
SetResponseHeaders(responseMessage, response);
if (bytes != null)
diff --git a/src/WireMock.Net/ResponseBuilders/IStatusCodeResponseBuilder.cs b/src/WireMock.Net/ResponseBuilders/IStatusCodeResponseBuilder.cs
index 9b8767af6..41777664b 100644
--- a/src/WireMock.Net/ResponseBuilders/IStatusCodeResponseBuilder.cs
+++ b/src/WireMock.Net/ResponseBuilders/IStatusCodeResponseBuilder.cs
@@ -14,6 +14,13 @@ public interface IStatusCodeResponseBuilder : IHeadersResponseBuilder
/// The .
IResponseBuilder WithStatusCode(int code);
+ ///
+ /// The with status code.
+ ///
+ /// The code.
+ /// The .
+ IResponseBuilder WithStatusCode(string code);
+
///
/// The with status code.
///
diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs
index 9d716286f..84151db10 100644
--- a/src/WireMock.Net/ResponseBuilders/Response.cs
+++ b/src/WireMock.Net/ResponseBuilders/Response.cs
@@ -87,11 +87,7 @@ private Response(ResponseMessage responseMessage)
ResponseMessage = responseMessage;
}
- ///
- /// The with status code.
- ///
- /// The code.
- /// A .\
+ ///
[PublicAPI]
public IResponseBuilder WithStatusCode(int code)
{
@@ -99,11 +95,15 @@ public IResponseBuilder WithStatusCode(int code)
return this;
}
- ///
- /// The with status code.
- ///
- /// The code.
- /// A .
+ ///
+ [PublicAPI]
+ public IResponseBuilder WithStatusCode(string code)
+ {
+ ResponseMessage.StatusCode = code;
+ return this;
+ }
+
+ ///
[PublicAPI]
public IResponseBuilder WithStatusCode(HttpStatusCode code)
{
diff --git a/src/WireMock.Net/ResponseMessage.cs b/src/WireMock.Net/ResponseMessage.cs
index a089aa3f2..669ef1293 100644
--- a/src/WireMock.Net/ResponseMessage.cs
+++ b/src/WireMock.Net/ResponseMessage.cs
@@ -19,7 +19,7 @@ public class ResponseMessage
///
/// Gets or sets the status code.
///
- public int StatusCode { get; set; } = 200;
+ public object StatusCode { get; set; } = 200;
///
/// Gets or sets the body.
diff --git a/src/WireMock.Net/Server/FluentMockServer.Admin.cs b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
index 94d94e198..cf26a7f1c 100644
--- a/src/WireMock.Net/Server/FluentMockServer.Admin.cs
+++ b/src/WireMock.Net/Server/FluentMockServer.Admin.cs
@@ -805,9 +805,15 @@ private IResponseBuilder InitResponseBuilder(ResponseModel responseModel)
return responseBuilder.WithProxy(proxyAndRecordSettings);
}
- if (responseModel.StatusCode.HasValue)
+ switch (responseModel.StatusCode)
{
- responseBuilder = responseBuilder.WithStatusCode(responseModel.StatusCode.Value);
+ case int statusCodeAsInteger:
+ responseBuilder = responseBuilder.WithStatusCode(statusCodeAsInteger);
+ break;
+
+ case string statusCodeAsString:
+ responseBuilder = responseBuilder.WithStatusCode(statusCodeAsString);
+ break;
}
if (responseModel.Headers != null)
diff --git a/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs b/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs
index 58d1d5d1e..c7bc75104 100644
--- a/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs
+++ b/src/WireMock.Net/Transformers/ResponseMessageTransformer.cs
@@ -1,4 +1,5 @@
-using JetBrains.Annotations;
+using HandlebarsDotNet;
+using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
@@ -24,14 +25,14 @@ public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage
{
var handlebarsContext = _factory.Create();
- var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
+ var responseMessage = new ResponseMessage();
var template = new { request = requestMessage };
switch (original.BodyData.DetectedBodyType)
{
case BodyType.Json:
- TransformBodyAsJson(handlebarsContext, template, original, responseMessage);
+ TransformBodyAsJson(handlebarsContext.Handlebars, template, original, responseMessage);
break;
case BodyType.File:
@@ -40,7 +41,7 @@ public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage
case BodyType.String:
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
- TransformBodyAsString(handlebarsContext, template, original, responseMessage);
+ TransformBodyAsString(handlebarsContext.Handlebars, template, original, responseMessage);
break;
}
@@ -62,29 +63,46 @@ public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage
responseMessage.Headers = newHeaders;
+ switch (original.StatusCode)
+ {
+ case int statusCodeAsInteger:
+ responseMessage.StatusCode = statusCodeAsInteger;
+ break;
+
+ case string statusCodeAsString:
+ var templateForStatusCode = handlebarsContext.Handlebars.Compile(statusCodeAsString);
+ responseMessage.StatusCode = templateForStatusCode(template);
+ break;
+ }
+
return responseMessage;
}
- private static void TransformBodyAsJson(IHandlebarsContext handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
+ private static void TransformBodyAsJson(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
{
JToken jToken;
switch (original.BodyData.BodyAsJson)
{
case JObject bodyAsJObject:
jToken = bodyAsJObject.DeepClone();
+ WalkNode(handlebarsContext, jToken, template);
break;
case Array bodyAsArray:
jToken = JArray.FromObject(bodyAsArray);
+ WalkNode(handlebarsContext, jToken, template);
+ break;
+
+ case string bodyAsString:
+ jToken = ReplaceSingleNode(handlebarsContext, bodyAsString, template);
break;
default:
jToken = JObject.FromObject(original.BodyData.BodyAsJson);
+ WalkNode(handlebarsContext, jToken, template);
break;
}
- WalkNode(handlebarsContext, jToken, template);
-
responseMessage.BodyData = new BodyData
{
DetectedBodyType = original.BodyData.DetectedBodyType,
@@ -93,7 +111,25 @@ private static void TransformBodyAsJson(IHandlebarsContext handlebarsContext, ob
};
}
- private static void WalkNode(IHandlebarsContext handlebarsContext, JToken node, object context)
+ private static JToken ReplaceSingleNode(IHandlebars handlebarsContext, string stringValue, object context)
+ {
+ var templateForStringValue = handlebarsContext.Compile(stringValue);
+ string transformedString = templateForStringValue(context);
+ if (!string.Equals(stringValue, transformedString))
+ {
+ const string property = "_";
+ JObject dummy = JObject.Parse($"{{ \"{property}\": null }}");
+ JToken node = dummy[property];
+
+ ReplaceNodeValue(node, transformedString);
+
+ return dummy[property];
+ }
+
+ return stringValue;
+ }
+
+ private static void WalkNode(IHandlebars handlebarsContext, JToken node, object context)
{
if (node.Type == JTokenType.Object)
{
@@ -120,7 +156,7 @@ private static void WalkNode(IHandlebarsContext handlebarsContext, JToken node,
return;
}
- var templateForStringValue = handlebarsContext.Handlebars.Compile(stringValue);
+ var templateForStringValue = handlebarsContext.Compile(stringValue);
string transformedString = templateForStringValue(context);
if (!string.Equals(stringValue, transformedString))
{
@@ -152,9 +188,9 @@ private static void ReplaceNodeValue(JToken node, string stringValue)
node.Replace(value);
}
- private static void TransformBodyAsString(IHandlebarsContext handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
+ private static void TransformBodyAsString(IHandlebars handlebarsContext, object template, ResponseMessage original, ResponseMessage responseMessage)
{
- var templateBodyAsString = handlebarsContext.Handlebars.Compile(original.BodyData.BodyAsString);
+ var templateBodyAsString = handlebarsContext.Compile(original.BodyData.BodyAsString);
responseMessage.BodyData = new BodyData
{
diff --git a/src/WireMock.Net/Util/HttpStatusRangeParser.cs b/src/WireMock.Net/Util/HttpStatusRangeParser.cs
index d838ea483..e0830acc6 100644
--- a/src/WireMock.Net/Util/HttpStatusRangeParser.cs
+++ b/src/WireMock.Net/Util/HttpStatusRangeParser.cs
@@ -10,6 +10,26 @@ namespace WireMock.Util
///
internal static class HttpStatusRangeParser
{
+ ///
+ /// Determines whether the specified pattern is match.
+ ///
+ /// The pattern. (Can be null, in that case it's allowed.)
+ /// The value.
+ /// is invalid.
+ public static bool IsMatch(string pattern, object httpStatusCode)
+ {
+ switch (httpStatusCode)
+ {
+ case int statusCodeAsInteger:
+ return IsMatch(pattern, statusCodeAsInteger);
+
+ case string statusCodeAsString:
+ return IsMatch(pattern, int.Parse(statusCodeAsString));
+ }
+
+ return false;
+ }
+
///
/// Determines whether the specified pattern is match.
///
diff --git a/src/WireMock.Net/WireMock.Net.csproj b/src/WireMock.Net/WireMock.Net.csproj
index f5d74ddd2..6518f6eeb 100644
--- a/src/WireMock.Net/WireMock.Net.csproj
+++ b/src/WireMock.Net/WireMock.Net.csproj
@@ -4,6 +4,7 @@
WireMock.Net
Stef Heyenrath
+
net451;net452;net46;net461;netstandard1.3;netstandard2.0
true
WireMock.Net
diff --git a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
index 26da3474b..bcb4764e8 100644
--- a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
+++ b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
@@ -78,7 +78,7 @@ public async void WireMockMiddleware_Invoke_NoMatch()
// Assert and Verify
_optionsMock.Verify(o => o.Logger.Warn(It.IsAny(), It.IsAny