From 8ba9c40d6599fe4eb9a5367f9d947dfcaf2592a9 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Fri, 28 Jun 2019 16:03:21 -0700 Subject: [PATCH 1/2] don't strip request body if we don't recognize the request method --- src/WireMock.Net/Util/BodyParser.cs | 28 ++++++++- .../FluentMockServerTests.cs | 59 +++++++++++++++++++ .../Util/BodyParserTests.cs | 23 ++++++++ 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index e29a05bcd..247566942 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -2,6 +2,7 @@ using MimeKit; using Newtonsoft.Json; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; @@ -27,7 +28,18 @@ internal static class BodyParser CONNECT - No defined body semantics PATCH - Body supported. */ - private static readonly string[] AllowedBodyParseMethods = { "PUT", "POST", "OPTIONS", "PATCH" }; + private static readonly IDictionary BodyAllowedForMethods = new Dictionary + { + { "HEAD", false }, + { "GET", false }, + { "PUT", true }, + { "POST", true }, + { "DELETE", false }, + { "TRACE", false }, + { "OPTIONS", true }, + { "CONNECT", false }, + { "PATCH", true } + }; private static readonly IStringMatcher[] MultipartContentTypesMatchers = { new WildcardMatcher("multipart/*", true) @@ -53,7 +65,19 @@ public static bool ParseBodyAsIsValid([CanBeNull] string parseBodyAs) public static bool ShouldParseBody([CanBeNull] string method) { - return AllowedBodyParseMethods.Contains(method, StringComparer.OrdinalIgnoreCase); + if (method == null) + { + return false; + } + 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 + // the HTTP Method Registry, we only really need to add it to BodyAllowedForMethods if + // we want to make it clear that a body is *not* allowed. + return true; } public static BodyType DetectBodyTypeFromContentType([CanBeNull] string contentTypeValue) diff --git a/test/WireMock.Net.Tests/FluentMockServerTests.cs b/test/WireMock.Net.Tests/FluentMockServerTests.cs index 5b6f00745..4499c0630 100644 --- a/test/WireMock.Net.Tests/FluentMockServerTests.cs +++ b/test/WireMock.Net.Tests/FluentMockServerTests.cs @@ -1,6 +1,7 @@ using NFluent; using System; using System.Diagnostics; +using System.Net; using System.Net.Http; using System.Threading.Tasks; using WireMock.RequestBuilders; @@ -172,5 +173,63 @@ public async Task FluentMockServer_Should_exclude_restrictedResponseHeader() Check.That(response.Headers.Contains("test")).IsTrue(); Check.That(response.Headers.Contains("Transfer-Encoding")).IsFalse(); } + + [Theory] + [InlineData("GET")] + [InlineData("TRACE")] + [InlineData("DELETE")] + public async Task FluentMockServer_Should_exclude_body_for_methods_where_body_is_definitely_disallowed(string method) + { + // Assign + string content = "hello"; + var server = FluentMockServer.Start(); + + server + .Given(Request.Create().WithBody(b => true)) + .AtPriority(0) + .RespondWith(Response.Create().WithStatusCode(400)); + server + .Given(Request.Create()) + .AtPriority(1) + .RespondWith(Response.Create().WithStatusCode(200)); + + // Act + var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost:" + server.Ports[0] + "/"); + request.Content = new StringContent(content); + var response = await new HttpClient().SendAsync(request); + + // Assert + Check.That(response.StatusCode).Equals(HttpStatusCode.OK); + } + + [Theory] + [InlineData("POST")] + [InlineData("PUT")] + [InlineData("OPTIONS")] + [InlineData("REPORT")] + [InlineData("SOME-UNKNOWN-METHOD")] // default behavior for unknown methods is to allow a body (see BodyParser.ShouldParseBody) + public async Task FluentMockServer_Should_not_exclude_body_for_supported_methods(string method) + { + // Assign + string content = "hello"; + var server = FluentMockServer.Start(); + + server + .Given(Request.Create().WithBody(content)) + .AtPriority(0) + .RespondWith(Response.Create().WithStatusCode(200)); + server + .Given(Request.Create()) + .AtPriority(1) + .RespondWith(Response.Create().WithStatusCode(400)); + + // Act + var request = new HttpRequestMessage(new HttpMethod(method), "http://localhost:" + server.Ports[0] + "/"); + request.Content = new StringContent(content); + var response = await new HttpClient().SendAsync(request); + + // Assert + Check.That(response.StatusCode).Equals(HttpStatusCode.OK); + } } } \ No newline at end of file diff --git a/test/WireMock.Net.Tests/Util/BodyParserTests.cs b/test/WireMock.Net.Tests/Util/BodyParserTests.cs index 62fa4ebb9..436407c41 100644 --- a/test/WireMock.Net.Tests/Util/BodyParserTests.cs +++ b/test/WireMock.Net.Tests/Util/BodyParserTests.cs @@ -125,5 +125,28 @@ public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType); } + + [Theory] + [InlineData("HEAD", false)] + [InlineData("GET", false)] + [InlineData("PUT", true)] + [InlineData("POST", true)] + [InlineData("DELETE", false)] + [InlineData("TRACE", false)] + [InlineData("OPTIONS", true)] + [InlineData("CONNECT", false)] + [InlineData("PATCH", true)] + public void BodyParser_ShouldParseBody_ExpectedResultForKnownMethods(string method, bool resultShouldBe) + { + Check.That(BodyParser.ShouldParseBody(method)).Equals(resultShouldBe); + } + + [Theory] + [InlineData("REPORT")] + [InlineData("SOME-UNKNOWN-METHOD")] + public void BodyParser_ShouldParseBody_DefaultIsTrueForUnknownMethods(string method) + { + Check.That(BodyParser.ShouldParseBody(method)).IsTrue(); + } } } \ No newline at end of file From 06a7395dfaf00cc6ee38e3815c0af52e55268ab3 Mon Sep 17 00:00:00 2001 From: Eli Bishop Date: Mon, 1 Jul 2019 10:21:08 -0700 Subject: [PATCH 2/2] use IsNullOrEmpty --- src/WireMock.Net/Util/BodyParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index 247566942..f31901be4 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -65,7 +65,7 @@ public static bool ParseBodyAsIsValid([CanBeNull] string parseBodyAs) public static bool ShouldParseBody([CanBeNull] string method) { - if (method == null) + if (String.IsNullOrEmpty(method)) { return false; }