diff --git a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
index 3faf8c718..b73e7e3a7 100644
--- a/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
+++ b/src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
@@ -145,17 +145,17 @@ private double CalculateMatchScore(RequestMessage requestMessage)
if (Func != null)
{
- return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.String && Func(requestMessage.BodyData.BodyAsString));
+ return MatchScores.ToScore(Func(requestMessage?.BodyData?.BodyAsString));
}
if (JsonFunc != null)
{
- return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.Json && JsonFunc(requestMessage.BodyData.BodyAsJson));
+ return MatchScores.ToScore(JsonFunc(requestMessage?.BodyData?.BodyAsJson));
}
if (DataFunc != null)
{
- return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.Bytes && DataFunc(requestMessage.BodyData.BodyAsBytes));
+ return MatchScores.ToScore(DataFunc(requestMessage?.BodyData?.BodyAsBytes));
}
return MatchScores.Mismatch;
diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs
index fea3110df..bda8c7c5a 100644
--- a/src/WireMock.Net/Util/BodyParser.cs
+++ b/src/WireMock.Net/Util/BodyParser.cs
@@ -13,8 +13,8 @@ namespace WireMock.Util
{
internal static class BodyParser
{
- private static readonly Encoding DefaultEncoding = Encoding.UTF8;
- private static readonly Encoding[] SupportedBodyAsStringEncodingForMultipart = { Encoding.UTF8, Encoding.ASCII };
+ private static readonly Encoding DefaultEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
+ private static readonly Encoding[] SupportedBodyAsStringEncodingForMultipart = { DefaultEncoding, Encoding.ASCII };
/*
HEAD - No defined body semantics.
diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
index be00d225f..bc1da82a3 100644
--- a/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
+++ b/test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
@@ -6,6 +6,7 @@
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
+using FluentAssertions;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
@@ -308,6 +309,43 @@ public async Task FluentMockServer_Proxy_Should_preserve_cookie_header_in_proxie
Check.That(receivedRequest.Cookies).ContainsPair("name", "value");
}
+ ///
+ /// Send some binary content in a request through the proxy and check that the same content
+ /// arrived at the target. As example a JPEG/JIFF header is used, which is not representable
+ /// in UTF8 and breaks if it is not treated as binary content.
+ ///
+ [Fact]
+ public async Task FluentMockServer_Proxy_Should_preserve_binary_request_content()
+ {
+ // arrange
+ var jpegHeader = new byte[] {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00};
+ var brokenJpegHeader = new byte[]
+ {0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD, 0xEF, 0xBF, 0xBD, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00};
+
+ bool HasCorrectHeader(byte[] bytes) => bytes.SequenceEqual(jpegHeader);
+ bool HasBrokenHeader(byte[] bytes) => bytes.SequenceEqual(brokenJpegHeader);
+
+ var serverForProxyForwarding = FluentMockServer.Start();
+ serverForProxyForwarding
+ .Given(Request.Create().WithBody(HasCorrectHeader))
+ .RespondWith(Response.Create().WithSuccess());
+
+ serverForProxyForwarding
+ .Given(Request.Create().WithBody(HasBrokenHeader))
+ .RespondWith(Response.Create().WithStatusCode(HttpStatusCode.InternalServerError));
+
+ var server = FluentMockServer.Start();
+ server
+ .Given(Request.Create())
+ .RespondWith(Response.Create().WithProxy(serverForProxyForwarding.Urls[0]));
+
+ // act
+ var response = await new HttpClient().PostAsync(server.Urls[0], new ByteArrayContent(jpegHeader));
+
+ // assert
+ Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.OK);
+ }
+
[Fact]
public async Task FluentMockServer_Proxy_Should_set_BodyAsJson_in_proxied_response()
{
diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs
index 97bdead27..22ddc1d79 100644
--- a/test/WireMock.Net.Tests/FluentMockServerTests.cs
+++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs
@@ -187,7 +187,7 @@ public async Task FluentMockServer_Should_exclude_body_for_methods_where_body_is
var server = FluentMockServer.Start();
server
- .Given(Request.Create().WithBody(b => true))
+ .Given(Request.Create().WithBody((byte[] bodyBytes) => bodyBytes != null))
.AtPriority(0)
.RespondWith(Response.Create().WithStatusCode(400));
server
diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs
index f21730240..a860aebc0 100644
--- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs
+++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs
@@ -1,5 +1,10 @@
-using System.Linq;
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
using Moq;
+using Newtonsoft.Json;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
@@ -208,5 +213,74 @@ public void RequestMessageBodyMatcher_GetMatchingScore_BodyAsBytes_IObjectMatche
// Verify
objectMatcherMock.Verify(m => m.IsMatch(It.IsAny()), Times.Once);
}
+
+ [Theory]
+ [MemberData(nameof(MatchingScoreData))]
+ public async Task RequestMessageBodyMatcher_GetMatchingScore_Funcs_Matching(object body, RequestMessageBodyMatcher matcher, bool shouldMatch)
+ {
+ // assign
+ BodyData bodyData;
+ if (body is byte[] b)
+ bodyData = await BodyParser.Parse(new MemoryStream(b), null);
+ else if (body is string s)
+ bodyData = await BodyParser.Parse(new MemoryStream(Encoding.UTF8.GetBytes(s)), null);
+ else
+ throw new Exception();
+
+ var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", bodyData);
+
+ // act
+ var result = new RequestMatchResult();
+ var score = matcher.GetMatchingScore(requestMessage, result);
+
+ // assert
+ Check.That(score).IsEqualTo(shouldMatch ? 1d : 0d);
+ }
+
+ public static TheoryData