From 88dd1b9aa43bcf0f4600abdf81499a9893396f8a Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Thu, 5 Mar 2020 17:59:24 +0100 Subject: [PATCH] Option to disable JSON deserialization (#434) * Option to disable JSON deserialization * Fix build errors, add test case * make new parameter optional * set default for contentType as well --- src/WireMock.Net/Http/HttpClientHelper.cs | 4 +-- .../Http/HttpResponseMessageHelper.cs | 4 +-- .../Owin/IWireMockMiddlewareOptions.cs | 2 ++ .../Owin/Mappers/OwinRequestMapper.cs | 2 +- .../Owin/WireMockMiddlewareOptions.cs | 3 ++ src/WireMock.Net/ResponseBuilders/Response.cs | 2 +- .../Server/WireMockServer.Admin.cs | 2 +- src/WireMock.Net/Server/WireMockServer.cs | 5 ++-- .../Settings/IWireMockServerSettings.cs | 6 ++++ .../Settings/WireMockServerSettings.cs | 4 +++ .../Settings/WireMockServerSettingsParser.cs | 3 +- src/WireMock.Net/Util/BodyParser.cs | 6 ++-- .../RequestMessageBodyMatcherTests.cs | 4 +-- .../Util/BodyParserTests.cs | 28 +++++++++++++++---- 14 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/WireMock.Net/Http/HttpClientHelper.cs b/src/WireMock.Net/Http/HttpClientHelper.cs index 296cdabc..550fa191 100644 --- a/src/WireMock.Net/Http/HttpClientHelper.cs +++ b/src/WireMock.Net/Http/HttpClientHelper.cs @@ -68,7 +68,7 @@ namespace WireMock.Http return client; } - public static async Task SendAsync([NotNull] HttpClient client, [NotNull] RequestMessage requestMessage, string url) + public static async Task SendAsync([NotNull] HttpClient client, [NotNull] RequestMessage requestMessage, string url, bool deserializeJson) { Check.NotNull(client, nameof(client)); Check.NotNull(requestMessage, nameof(requestMessage)); @@ -83,7 +83,7 @@ namespace WireMock.Http var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead); // Create ResponseMessage - return await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri); + return await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson); } } } \ No newline at end of file diff --git a/src/WireMock.Net/Http/HttpResponseMessageHelper.cs b/src/WireMock.Net/Http/HttpResponseMessageHelper.cs index f23c5acb..b73d881f 100644 --- a/src/WireMock.Net/Http/HttpResponseMessageHelper.cs +++ b/src/WireMock.Net/Http/HttpResponseMessageHelper.cs @@ -9,7 +9,7 @@ namespace WireMock.Http { internal static class HttpResponseMessageHelper { - public static async Task CreateAsync(HttpResponseMessage httpResponseMessage, Uri requiredUri, Uri originalUri) + public static async Task CreateAsync(HttpResponseMessage httpResponseMessage, Uri requiredUri, Uri originalUri, bool deserializeJson) { var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode }; @@ -24,7 +24,7 @@ namespace WireMock.Http contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value; } - responseMessage.BodyData = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault()); + responseMessage.BodyData = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault(), deserializeJson); } foreach (var header in headers) diff --git a/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs index 2684a890..1a89533d 100644 --- a/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/IWireMockMiddlewareOptions.cs @@ -41,5 +41,7 @@ namespace WireMock.Owin bool? AllowBodyForAllHttpMethods { get; set; } bool? AllowAnyHttpStatusCodeInResponse { get; set; } + + bool? DisableJsonBodyParsing { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs index c9ff92e6..a8e1a027 100644 --- a/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs +++ b/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs @@ -49,7 +49,7 @@ namespace WireMock.Owin.Mappers BodyData body = null; if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true)) { - body = await BodyParser.Parse(request.Body, request.ContentType); + body = await BodyParser.Parse(request.Body, request.ContentType, !options.DisableJsonBodyParsing.GetValueOrDefault(false)); } return new RequestMessage(urldetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow }; diff --git a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs index 91ed19ab..3599a249 100644 --- a/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs +++ b/src/WireMock.Net/Owin/WireMockMiddlewareOptions.cs @@ -45,5 +45,8 @@ namespace WireMock.Owin /// public bool? AllowAnyHttpStatusCodeInResponse { get; set; } + + /// + public bool? DisableJsonBodyParsing { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/ResponseBuilders/Response.cs b/src/WireMock.Net/ResponseBuilders/Response.cs index 07680b58..3663eb3d 100644 --- a/src/WireMock.Net/ResponseBuilders/Response.cs +++ b/src/WireMock.Net/ResponseBuilders/Response.cs @@ -366,7 +366,7 @@ namespace WireMock.ResponseBuilders var proxyUri = new Uri(ProxyUrl); var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); - return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri); + return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, !settings.DisableJsonBodyParsing.GetValueOrDefault(false)); } if (UseTransformer) diff --git a/src/WireMock.Net/Server/WireMockServer.Admin.cs b/src/WireMock.Net/Server/WireMockServer.Admin.cs index da36e2fa..feb470a0 100644 --- a/src/WireMock.Net/Server/WireMockServer.Admin.cs +++ b/src/WireMock.Net/Server/WireMockServer.Admin.cs @@ -275,7 +275,7 @@ namespace WireMock.Server var proxyUri = new Uri(settings.ProxyAndRecordSettings.Url); var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); - var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri); + var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, !settings.DisableJsonBodyParsing.GetValueOrDefault(false)); if (HttpStatusRangeParser.IsMatch(settings.ProxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) && (settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile)) diff --git a/src/WireMock.Net/Server/WireMockServer.cs b/src/WireMock.Net/Server/WireMockServer.cs index 81b9f61a..891203da 100644 --- a/src/WireMock.Net/Server/WireMockServer.cs +++ b/src/WireMock.Net/Server/WireMockServer.cs @@ -213,9 +213,10 @@ namespace WireMock.Server } _options.FileSystemHandler = _settings.FileSystemHandler; - _options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit; - _options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit; + _options.PreWireMockMiddlewareInit = _settings.PreWireMockMiddlewareInit; + _options.PostWireMockMiddlewareInit = _settings.PostWireMockMiddlewareInit; _options.Logger = _settings.Logger; + _options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing; _matcherMapper = new MatcherMapper(_settings); _mappingConverter = new MappingConverter(_matcherMapper); diff --git a/src/WireMock.Net/Settings/IWireMockServerSettings.cs b/src/WireMock.Net/Settings/IWireMockServerSettings.cs index 0238d95f..d11490b8 100644 --- a/src/WireMock.Net/Settings/IWireMockServerSettings.cs +++ b/src/WireMock.Net/Settings/IWireMockServerSettings.cs @@ -143,5 +143,11 @@ namespace WireMock.Settings /// /// [PublicAPI] bool? AllowAnyHttpStatusCodeInResponse { get; set; } + + /// + /// Set to true to disable Json deserialization when processing requests. (default set to false). + /// + [PublicAPI] + bool? DisableJsonBodyParsing { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Settings/WireMockServerSettings.cs b/src/WireMock.Net/Settings/WireMockServerSettings.cs index 7121c3b4..f05b993d 100644 --- a/src/WireMock.Net/Settings/WireMockServerSettings.cs +++ b/src/WireMock.Net/Settings/WireMockServerSettings.cs @@ -104,5 +104,9 @@ namespace WireMock.Settings /// public bool? AllowAnyHttpStatusCodeInResponse { get; set; } + + /// + [PublicAPI] + public bool? DisableJsonBodyParsing { get; set; } } } \ No newline at end of file diff --git a/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs b/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs index c233be7b..ed5c0ecf 100644 --- a/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs +++ b/src/WireMock.Net/Settings/WireMockServerSettingsParser.cs @@ -35,7 +35,8 @@ namespace WireMock.Settings RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"), AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"), AllowBodyForAllHttpMethods = parser.GetBoolValue("AllowBodyForAllHttpMethods"), - AllowAnyHttpStatusCodeInResponse = parser.GetBoolValue("AllowAnyHttpStatusCodeInResponse") + AllowAnyHttpStatusCodeInResponse = parser.GetBoolValue("AllowAnyHttpStatusCodeInResponse"), + DisableJsonBodyParsing = parser.GetBoolValue("DisableJsonBodyParsing") }; if (logger != null) diff --git a/src/WireMock.Net/Util/BodyParser.cs b/src/WireMock.Net/Util/BodyParser.cs index 546e93c4..70a675e2 100644 --- a/src/WireMock.Net/Util/BodyParser.cs +++ b/src/WireMock.Net/Util/BodyParser.cs @@ -108,7 +108,7 @@ namespace WireMock.Util return BodyType.Bytes; } - public static async Task Parse([NotNull] Stream stream, [CanBeNull] string contentType) + public static async Task Parse([NotNull] Stream stream, [CanBeNull] string contentType = null, bool deserializeJson = true) { Check.NotNull(stream, nameof(stream)); @@ -128,8 +128,6 @@ namespace WireMock.Util data.BodyAsString = encoding.GetString(data.BodyAsBytes); data.Encoding = encoding; data.DetectedBodyType = BodyType.String; - - return data; } return data; @@ -143,7 +141,7 @@ namespace WireMock.Util data.DetectedBodyType = BodyType.String; // If string is not null or empty, try to deserialize the string to a JObject - if (!string.IsNullOrEmpty(data.BodyAsString)) + if (deserializeJson && !string.IsNullOrEmpty(data.BodyAsString)) { try { diff --git a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs index ab64189d..18f0f904 100644 --- a/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs +++ b/test/WireMock.Net.Tests/RequestMatchers/RequestMessageBodyMatcherTests.cs @@ -243,9 +243,9 @@ namespace WireMock.Net.Tests.RequestMatchers // assign BodyData bodyData; if (body is byte[] b) - bodyData = await BodyParser.Parse(new MemoryStream(b), null); + bodyData = await BodyParser.Parse(new MemoryStream(b), null, true); else if (body is string s) - bodyData = await BodyParser.Parse(new MemoryStream(Encoding.UTF8.GetBytes(s)), null); + bodyData = await BodyParser.Parse(new MemoryStream(Encoding.UTF8.GetBytes(s)), null, true); else throw new Exception(); diff --git a/test/WireMock.Net.Tests/Util/BodyParserTests.cs b/test/WireMock.Net.Tests/Util/BodyParserTests.cs index 63b71500..9538de94 100644 --- a/test/WireMock.Net.Tests/Util/BodyParserTests.cs +++ b/test/WireMock.Net.Tests/Util/BodyParserTests.cs @@ -22,7 +22,7 @@ namespace WireMock.Net.Tests.Util var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson)); // Act - var body = await BodyParser.Parse(memoryStream, contentType); + var body = await BodyParser.Parse(memoryStream, contentType, true); // Assert Check.That(body.BodyAsBytes).IsNotNull(); @@ -41,7 +41,7 @@ namespace WireMock.Net.Tests.Util var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)); // Act - var body = await BodyParser.Parse(memoryStream, contentType); + var body = await BodyParser.Parse(memoryStream, contentType, true); // Assert Check.That(body.BodyAsBytes).IsNotNull(); @@ -61,7 +61,23 @@ namespace WireMock.Net.Tests.Util var memoryStream = new MemoryStream(content); // act - var body = await BodyParser.Parse(memoryStream, null); + var body = await BodyParser.Parse(memoryStream, null, true); + + // assert + Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); + } + + [Theory] + [InlineData(new byte[] { 34, 97, 34 }, BodyType.String)] + [InlineData(new byte[] { 97 }, BodyType.String)] + [InlineData(new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 }, BodyType.Bytes)] + public async Task BodyParser_Parse_DetectedBodyTypeNoJsonParsing(byte[] content, BodyType detectedBodyType) + { + // arrange + var memoryStream = new MemoryStream(content); + + // act + var body = await BodyParser.Parse(memoryStream, null, false); // assert Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); @@ -95,7 +111,7 @@ Content-Type: text/html var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(body)); // Act - var result = await BodyParser.Parse(memoryStream, contentType); + var result = await BodyParser.Parse(memoryStream, contentType, true); // Assert Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String); @@ -115,7 +131,7 @@ Content-Type: text/html var memoryStream = new MemoryStream(Encoding.UTF32.GetBytes(body)); // Act - var result = await BodyParser.Parse(memoryStream, contentType); + var result = await BodyParser.Parse(memoryStream, contentType, true); // Assert Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes); @@ -133,7 +149,7 @@ Content-Type: text/html var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)); // Act - var body = await BodyParser.Parse(memoryStream, contentType); + var body = await BodyParser.Parse(memoryStream, contentType, true); // Assert Check.That(body.BodyAsBytes).IsNotNull();