Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix issues with Proxy mode and Binary Request Bodies #334

Merged
merged 9 commits into from
Sep 1, 2019
14 changes: 7 additions & 7 deletions src/WireMock.Net/Matchers/Request/RequestMessageBodyMatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,20 +142,20 @@ private double CalculateMatchScore(RequestMessage requestMessage)
{
return Matchers.Max(matcher => CalculateMatchScore(requestMessage, matcher));
}

if (Func != null)
if (Func != null && requestMessage?.BodyData?.BodyAsString != null)
andi0b marked this conversation as resolved.
Show resolved Hide resolved
{
return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.String && Func(requestMessage.BodyData.BodyAsString));
return MatchScores.ToScore(Func(requestMessage.BodyData.BodyAsString));
andi0b marked this conversation as resolved.
Show resolved Hide resolved
}

if (JsonFunc != null)
if (JsonFunc != null && requestMessage?.BodyData?.BodyAsJson != null)
{
return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.Json && JsonFunc(requestMessage.BodyData.BodyAsJson));
return MatchScores.ToScore( JsonFunc(requestMessage.BodyData.BodyAsJson));
}

if (DataFunc != null)
if (DataFunc != null && requestMessage?.BodyData?.BodyAsBytes != null)
{
return MatchScores.ToScore(requestMessage?.BodyData?.DetectedBodyType == BodyType.Bytes && DataFunc(requestMessage.BodyData.BodyAsBytes));
return MatchScores.ToScore(DataFunc(requestMessage.BodyData.BodyAsBytes));
}

return MatchScores.Mismatch;
Expand Down
16 changes: 8 additions & 8 deletions src/WireMock.Net/Util/BodyParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,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.
Expand Down Expand Up @@ -65,13 +65,13 @@ public static bool ParseBodyAsIsValid([CanBeNull] string parseBodyAs)

public static bool ShouldParseBody([CanBeNull] string method)
{
if (String.IsNullOrEmpty(method))
{
return false;
if (String.IsNullOrEmpty(method))
{
return false;
}
if (BodyAllowedForMethods.TryGetValue(method.ToUpper(), out var allowed))
{
return allowed;
if (BodyAllowedForMethods.TryGetValue(method.ToUpper(), out var allowed))
{
return allowed;
}
// If we don't have any knowledge of this method, we should assume that a body *may*
// be present, so we should parse it if it is. Therefore, if a new method is added to
Expand Down
38 changes: 38 additions & 0 deletions test/WireMock.Net.Tests/FluentMockServerTests.Proxy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -308,6 +309,43 @@ public async Task FluentMockServer_Proxy_Should_preserve_cookie_header_in_proxie
Check.That(receivedRequest.Cookies).ContainsPair("name", "value");
}

/// <summary>
andi0b marked this conversation as resolved.
Show resolved Hide resolved
/// 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.
/// </summary>
[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()
{
Expand Down