Compare commits

..

4 Commits

Author SHA1 Message Date
Stef Heyenrath
e701566a1f 1.0.34.0 2019-10-22 21:09:48 +02:00
Stef Heyenrath
84ad5a927e 2.x.x (#366) 2019-10-22 18:58:36 +00:00
Stef Heyenrath
3250604b5a #352 (#354) 2019-10-22 18:53:30 +00:00
dependabot[bot]
9d2963632e Bump Microsoft.AspNetCore.All in /examples/WireMock.Net.WebApplication (#365)
Bumps [Microsoft.AspNetCore.All](https://github.com/aspnet/Universe) from 2.0.8 to 2.0.9.
- [Release notes](https://github.com/aspnet/Universe/releases)
- [Changelog](https://github.com/aspnet/Universe/blob/master/docs/CrossRepoBreakingChanges.md)
- [Commits](https://github.com/aspnet/Universe/compare/2.0.8...2.0.9)

Signed-off-by: dependabot[bot] <support@github.com>
2019-10-22 09:32:37 +00:00
21 changed files with 263 additions and 185 deletions

View File

@@ -1,3 +1,9 @@
# 1.0.34.0 (22 October 2019)
- [#354](https://github.com/WireMock-Net/WireMock.Net/pull/354) - AllowBodyForAllHttpMethods [bug, feature] contributed by [StefH](https://github.com/StefH)
- [#365](https://github.com/WireMock-Net/WireMock.Net/pull/365) - Bump Microsoft.AspNetCore.All from 2.0.8 to 2.0.9 in /examples/WireMock.Net.WebApplication [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#366](https://github.com/WireMock-Net/WireMock.Net/pull/366) - Update ObsoleteAnnotations [feature] contributed by [StefH](https://github.com/StefH)
- [#352](https://github.com/WireMock-Net/WireMock.Net/issues/352) - DELETE request drops the body [feature, question]
# 1.0.33.0 (12 October 2019)
- [#311](https://github.com/WireMock-Net/WireMock.Net/pull/311) - fix jsonpath matcher [bug] contributed by [StefH](https://github.com/StefH)
- [#324](https://github.com/WireMock-Net/WireMock.Net/pull/324) - Add CSharpCodeMatcher [feature] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.0.33</VersionPrefix>
<VersionPrefix>1.0.34</VersionPrefix>
</PropertyGroup>
<Choose>

View File

@@ -1,3 +1,3 @@
https://github.com/StefH/GitHubReleaseNotes
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid --version 1.0.33.0
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid --version 1.0.34.0

View File

@@ -11,7 +11,7 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0'">
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.8" />
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>

View File

@@ -11,7 +11,6 @@ namespace WireMock.Net.StandAlone
/// <summary>
/// The StandAloneApp
/// </summary>
[Obsolete("This class will be removed in version 1.1.0")]
public static class StandAloneApp
{
/// <summary>
@@ -19,7 +18,6 @@ namespace WireMock.Net.StandAlone
/// </summary>
/// <param name="settings">The FluentMockServerSettings</param>
[PublicAPI]
[Obsolete("Will be replaced by WireMockServer.Start(settings) in version 1.1.0")]
public static FluentMockServer Start([NotNull] IFluentMockServerSettings settings)
{
Check.NotNull(settings, nameof(settings));
@@ -37,7 +35,6 @@ namespace WireMock.Net.StandAlone
/// <param name="args">The commandline arguments</param>
/// <param name="logger">The logger</param>
[PublicAPI]
[Obsolete("Will be replaced by `var settings = WireMockServerSettingsParser.ParseArguments(args, logger); WireMockServer.Start(settings);` in version 1.1.0")]
public static FluentMockServer Start([NotNull] string[] args, [CanBeNull] IWireMockLogger logger = null)
{
Check.NotNull(args, nameof(args));
@@ -56,6 +53,7 @@ namespace WireMock.Net.StandAlone
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),
AllowBodyForAllHttpMethods = parser.GetBoolValue("AllowBodyForAllHttpMethods")
};
if (logger != null)

View File

@@ -24,5 +24,10 @@
/// Gets or sets the MaxRequestLog count.
/// </summary>
public int? MaxRequestLogCount { get; set; }
/// <summary>
/// Gets or sets wether to allow a body for all HTTP methods.
/// </summary>
public bool? AllowBodyForAllHttpMethods { get; set; }
}
}

View File

@@ -20,7 +20,7 @@ namespace WireMock.Owin
IStringMatcher AuthorizationMatcher { get; set; }
bool AllowPartialMapping { get; set; }
bool? AllowPartialMapping { get; set; }
ConcurrentDictionary<Guid, IMapping> Mappings { get; }
@@ -37,5 +37,7 @@ namespace WireMock.Owin
Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; }
IFileSystemHandler FileSystemHandler { get; set; }
bool? AllowBodyForAllHttpMethods { get; set; }
}
}

View File

@@ -16,7 +16,8 @@ namespace WireMock.Owin.Mappers
/// MapAsync IRequest to RequestMessage
/// </summary>
/// <param name="request">The OwinRequest/HttpRequest</param>
/// <param name="options">The WireMockMiddlewareOptions</param>
/// <returns>RequestMessage</returns>
Task<RequestMessage> MapAsync(IRequest request);
Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddlewareOptions options);
}
}

View File

@@ -20,7 +20,7 @@ namespace WireMock.Owin.Mappers
internal class OwinRequestMapper : IOwinRequestMapper
{
/// <inheritdoc cref="IOwinRequestMapper.MapAsync"/>
public async Task<RequestMessage> MapAsync(IRequest request)
public async Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddlewareOptions options)
{
(UrlDetails urldetails, string clientIP) = ParseRequest(request);
@@ -47,7 +47,7 @@ namespace WireMock.Owin.Mappers
}
BodyData body = null;
if (request.Body != null && BodyParser.ShouldParseBody(method))
if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true))
{
body = await BodyParser.Parse(request.Body, request.ContentType);
}

View File

@@ -37,7 +37,7 @@ namespace WireMock.Owin
}
}
if (_options.AllowPartialMapping)
if (_options.AllowPartialMapping == true)
{
var partialMappings = mappings
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)

View File

@@ -69,7 +69,7 @@ namespace WireMock.Owin
private async Task InvokeInternal(IContext ctx)
{
var request = await _requestMapper.MapAsync(ctx.Request);
var request = await _requestMapper.MapAsync(ctx.Request, _options);
bool logRequest = false;
ResponseMessage response = null;

View File

@@ -21,7 +21,7 @@ namespace WireMock.Owin
public IStringMatcher AuthorizationMatcher { get; set; }
public bool AllowPartialMapping { get; set; }
public bool? AllowPartialMapping { get; set; }
public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>();
@@ -39,5 +39,8 @@ namespace WireMock.Owin
/// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/>
public IFileSystemHandler FileSystemHandler { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowBodyForAllHttpMethods"/>
public bool? AllowBodyForAllHttpMethods { get; set; }
}
}

View File

@@ -339,7 +339,8 @@ namespace WireMock.Server
AllowPartialMapping = _options.AllowPartialMapping,
MaxRequestLogCount = _options.MaxRequestLogCount,
RequestLogExpirationDuration = _options.RequestLogExpirationDuration,
GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds
GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds,
AllowBodyForAllHttpMethods = _options.AllowBodyForAllHttpMethods
};
return ToJson(model);
@@ -361,6 +362,11 @@ namespace WireMock.Server
_options.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value);
}
if (settings.AllowBodyForAllHttpMethods != null)
{
_options.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods.Value;
}
return ResponseMessageBuilder.Create("Settings updated");
}
#endregion Settings

View File

@@ -1,11 +1,11 @@
using JetBrains.Annotations;
using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Admin.Mappings;
using WireMock.Exceptions;
using WireMock.Handlers;
@@ -25,7 +25,7 @@ namespace WireMock.Server
/// <summary>
/// The fluent mock server.
/// </summary>
[Obsolete("Will be replaced by WireMockServer in version 1.1.0")]
[Obsolete("Will be replaced by WireMockServer in version 2.x.x")]
public partial class FluentMockServer : IDisposable
{
private const int ServerStartDelayInMs = 100;
@@ -257,6 +257,12 @@ namespace WireMock.Server
}
}
if (settings.AllowBodyForAllHttpMethods == true)
{
_options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods;
_settings.Logger.Info("AllowBodyForAllHttpMethods is set to {0}", _settings.AllowBodyForAllHttpMethods == true);
}
if (settings.AllowPartialMapping == true)
{
AllowPartialMapping();

View File

@@ -10,7 +10,7 @@ namespace WireMock.Settings
/// <summary>
/// FluentMockServerSettings
/// </summary>
[Obsolete("Will be replaced by WireMockServerSettings in version 1.1.0")]
[Obsolete("Will be replaced by WireMockServerSettings in version 2.x.x")]
public class FluentMockServerSettings : IFluentMockServerSettings
{
/// <inheritdoc cref="IFluentMockServerSettings.Port"/>
@@ -94,5 +94,9 @@ namespace WireMock.Settings
/// <inheritdoc cref="IFluentMockServerSettings.AllowCSharpCodeMatcher"/>
[PublicAPI]
public bool? AllowCSharpCodeMatcher { get; set; }
/// <inheritdoc cref="IFluentMockServerSettings.AllowBodyForAllHttpMethods"/>
[PublicAPI]
public bool? AllowBodyForAllHttpMethods { get; set; }
}
}

View File

@@ -9,7 +9,7 @@ namespace WireMock.Settings
/// <summary>
/// IFluentMockServerSettings
/// </summary>
[Obsolete("This interface will be removed and replaced by the class WireMockServerSettings in version 1.1.0")]
[Obsolete("This interface will be removed and replaced by the class WireMockServerSettings in version 2.x.x")]
public interface IFluentMockServerSettings
{
/// <summary>
@@ -124,6 +124,13 @@ namespace WireMock.Settings
/// <summary>
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
/// </summary>
[PublicAPI]
bool? AllowCSharpCodeMatcher { get; set; }
/// <summary>
/// Allow a Body for all HTTP Methods. (default set to false).
/// </summary>
[PublicAPI]
bool? AllowBodyForAllHttpMethods { get; set; }
}
}

View File

@@ -7,7 +7,7 @@ namespace WireMock.Settings
/// <summary>
/// IProxyAndRecordSettings
/// </summary>
[Obsolete("This interface will be removed and replaced by the class ProxyAndRecordSettings in version 1.1.0")]
[Obsolete("This interface will be removed and replaced by the class ProxyAndRecordSettings in version 2.x.x")]
public interface IProxyAndRecordSettings
{
/// <summary>

View File

@@ -59,14 +59,19 @@ namespace WireMock.Util
private static readonly JsonSerializerSettings JsonSerializerSettings = new JsonSerializerSettings { DateParseHandling = DateParseHandling.None };
public static bool ShouldParseBody([CanBeNull] string method)
public static bool ShouldParseBody([CanBeNull] string httpMethod, bool allowBodyForAllHttpMethods)
{
if (string.IsNullOrEmpty(method))
if (string.IsNullOrEmpty(httpMethod))
{
return false;
}
if (BodyAllowedForMethods.TryGetValue(method.ToUpper(), out bool allowed))
if (allowBodyForAllHttpMethods)
{
return true;
}
if (BodyAllowedForMethods.TryGetValue(httpMethod.ToUpper(), out bool allowed))
{
return allowed;
}

View File

@@ -116,7 +116,25 @@ namespace WireMock.Net.Tests
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AllowPartialMapping).IsTrue();
Check.That(options.AllowPartialMapping).Equals(true);
// Verify
_loggerMock.Verify(l => l.Info(It.IsAny<string>(), It.IsAny<bool>()));
}
[Fact]
public void FluentMockServer_FluentMockServerSettings_AllowBodyForAllHttpMethods()
{
// Assign and Act
var server = FluentMockServer.Start(new FluentMockServerSettings
{
Logger = _loggerMock.Object,
AllowBodyForAllHttpMethods = true
});
// Assert
var options = server.GetPrivateFieldValue<IWireMockMiddlewareOptions>("_options");
Check.That(options.AllowBodyForAllHttpMethods).Equals(true);
// Verify
_loggerMock.Verify(l => l.Info(It.IsAny<string>(), It.IsAny<bool>()));

View File

@@ -52,7 +52,7 @@ namespace WireMock.Net.Tests.Owin
_requestMapperMock = new Mock<IOwinRequestMapper>();
_requestMapperMock.SetupAllProperties();
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>())).ReturnsAsync(request);
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_responseMapperMock = new Mock<IOwinResponseMapper>();
_responseMapperMock.SetupAllProperties();
@@ -87,7 +87,7 @@ namespace WireMock.Net.Tests.Owin
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]>());
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>())).ReturnsAsync(request);
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);
@@ -108,7 +108,7 @@ namespace WireMock.Net.Tests.Owin
{
// Assign
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1", null, new Dictionary<string, string[]> { { "h", new[] { "x" } } });
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>())).ReturnsAsync(request);
_requestMapperMock.Setup(m => m.MapAsync(It.IsAny<IRequest>(), It.IsAny<IWireMockMiddlewareOptions>())).ReturnsAsync(request);
_optionsMock.SetupGet(o => o.AuthorizationMatcher).Returns(new ExactMatcher());
_mappingMock.SetupGet(m => m.IsAdminInterface).Returns(true);

View File

@@ -1,168 +1,185 @@
using NFluent;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Util
{
public class BodyParserTests
{
[Theory]
[InlineData("application/json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/json; charset=utf-8", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/json; odata.metadata=minimal", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/vnd.api+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/vnd.test+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
public async Task BodyParser_Parse_ContentTypeJson(string contentType, string bodyAsJson, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{
// Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson));
// Act
var body = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(body.BodyAsBytes).IsNotNull();
Check.That(body.BodyAsJson).IsNotNull();
Check.That(body.BodyAsString).Equals(bodyAsJson);
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
}
[Theory]
[InlineData("application/xml", "<xml>hello</xml>", BodyType.String, BodyType.String)]
[InlineData("something", "hello", BodyType.String, BodyType.Bytes)]
public async Task BodyParser_Parse_ContentTypeString(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{
// Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
// Act
var body = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(body.BodyAsBytes).IsNotNull();
Check.That(body.BodyAsJson).IsNull();
Check.That(body.BodyAsString).Equals(bodyAsString);
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
}
[Theory]
[InlineData(new byte[] {34, 97, 34}, BodyType.Json)]
[InlineData(new byte[] {97}, BodyType.String)]
[InlineData(new byte[] {0xFF, 0xD8, 0xFF, 0xE0}, BodyType.Bytes)]
public async Task BodyParser_Parse_DetectedBodyType(byte[] content, BodyType detectedBodyType)
{
// arrange
var memoryStream = new MemoryStream(content);
// act
var body = await BodyParser.Parse(memoryStream, null);
// assert
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
}
[Fact]
public async Task BodyParser_Parse_WithUTF8EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
{
// Arrange
string contentType = "multipart/form-data";
string body = @"
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name=""text""
text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name=""file1""; filename=""a.txt""
Content-Type: text/plain
Content of a txt
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name=""file2""; filename=""a.html""
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------9051914041544843365972754266--";
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
// Act
var result = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String);
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
Check.That(result.BodyAsBytes).IsNotNull();
Check.That(result.BodyAsJson).IsNull();
Check.That(result.BodyAsString).IsNotNull();
}
[Fact]
public async Task BodyParser_Parse_WithUTF16EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
{
// Arrange
string contentType = "multipart/form-data";
string body = char.ConvertFromUtf32(0x1D161); //U+1D161 = MUSICAL SYMBOL SIXTEENTH NOTE
var memoryStream = new MemoryStream(Encoding.UTF32.GetBytes(body));
// Act
var result = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes);
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
Check.That(result.BodyAsBytes).IsNotNull();
Check.That(result.BodyAsJson).IsNull();
Check.That(result.BodyAsString).IsNull();
}
[Theory]
[InlineData(null, "hello", BodyType.String, BodyType.Bytes)]
public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{
// Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
// Act
var body = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(body.BodyAsBytes).IsNotNull();
Check.That(body.BodyAsJson).IsNull();
Check.That(body.BodyAsString).Equals(bodyAsString);
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)]
using NFluent;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Util
{
public class BodyParserTests
{
[Theory]
[InlineData("application/json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/json; charset=utf-8", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/json; odata.metadata=minimal", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/vnd.api+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
[InlineData("application/vnd.test+json", "{ \"x\": 1 }", BodyType.Json, BodyType.Json)]
public async Task BodyParser_Parse_ContentTypeJson(string contentType, string bodyAsJson, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{
// Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson));
// Act
var body = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(body.BodyAsBytes).IsNotNull();
Check.That(body.BodyAsJson).IsNotNull();
Check.That(body.BodyAsString).Equals(bodyAsJson);
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
}
[Theory]
[InlineData("application/xml", "<xml>hello</xml>", BodyType.String, BodyType.String)]
[InlineData("something", "hello", BodyType.String, BodyType.Bytes)]
public async Task BodyParser_Parse_ContentTypeString(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{
// Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
// Act
var body = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(body.BodyAsBytes).IsNotNull();
Check.That(body.BodyAsJson).IsNull();
Check.That(body.BodyAsString).Equals(bodyAsString);
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
}
[Theory]
[InlineData(new byte[] {34, 97, 34}, BodyType.Json)]
[InlineData(new byte[] {97}, BodyType.String)]
[InlineData(new byte[] {0xFF, 0xD8, 0xFF, 0xE0}, BodyType.Bytes)]
public async Task BodyParser_Parse_DetectedBodyType(byte[] content, BodyType detectedBodyType)
{
// arrange
var memoryStream = new MemoryStream(content);
// act
var body = await BodyParser.Parse(memoryStream, null);
// assert
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
}
[Fact]
public async Task BodyParser_Parse_WithUTF8EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
{
// Arrange
string contentType = "multipart/form-data";
string body = @"
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name=""text""
text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name=""file1""; filename=""a.txt""
Content-Type: text/plain
Content of a txt
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name=""file2""; filename=""a.html""
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------9051914041544843365972754266--";
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(body));
// Act
var result = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String);
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
Check.That(result.BodyAsBytes).IsNotNull();
Check.That(result.BodyAsJson).IsNull();
Check.That(result.BodyAsString).IsNotNull();
}
[Fact]
public async Task BodyParser_Parse_WithUTF16EncodingAndContentTypeMultipart_DetectedBodyTypeEqualsString()
{
// Arrange
string contentType = "multipart/form-data";
string body = char.ConvertFromUtf32(0x1D161); //U+1D161 = MUSICAL SYMBOL SIXTEENTH NOTE
var memoryStream = new MemoryStream(Encoding.UTF32.GetBytes(body));
// Act
var result = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes);
Check.That(result.DetectedBodyTypeFromContentType).IsEqualTo(BodyType.MultiPart);
Check.That(result.BodyAsBytes).IsNotNull();
Check.That(result.BodyAsJson).IsNull();
Check.That(result.BodyAsString).IsNull();
}
[Theory]
[InlineData(null, "hello", BodyType.String, BodyType.Bytes)]
public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{
// Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString));
// Act
var body = await BodyParser.Parse(memoryStream, contentType);
// Assert
Check.That(body.BodyAsBytes).IsNotNull();
Check.That(body.BodyAsJson).IsNull();
Check.That(body.BodyAsString).Equals(bodyAsString);
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)
[InlineData("PATCH", true)]
public void BodyParser_ShouldParseBodyForMethodAndAllowAllIsFalse_ExpectedResultForKnownMethods(string method, bool resultShouldBe)
{
Check.That(BodyParser.ShouldParseBody(method)).Equals(resultShouldBe);
Check.That(BodyParser.ShouldParseBody(method, false)).Equals(resultShouldBe);
}
[Theory]
[InlineData("REPORT")]
[InlineData("SOME-UNKNOWN-METHOD")]
[Theory]
[InlineData("HEAD")]
[InlineData("GET")]
[InlineData("PUT")]
[InlineData("POST")]
[InlineData("DELETE")]
[InlineData("TRACE")]
[InlineData("OPTIONS")]
[InlineData("CONNECT")]
[InlineData("PATCH")]
[InlineData("REPORT")]
[InlineData("SOME-UNKNOWN-METHOD")]
public void BodyParser_ShouldParseBodyForMethodAndAllowAllIsTrue_ExpectedResultShouldBeTrue(string method)
{
Check.That(BodyParser.ShouldParseBody(method, true)).IsTrue();
}
[Theory]
[InlineData("REPORT")]
[InlineData("SOME-UNKNOWN-METHOD")]
public void BodyParser_ShouldParseBody_DefaultIsTrueForUnknownMethods(string method)
{
Check.That(BodyParser.ShouldParseBody(method)).IsTrue();
}
}
Check.That(BodyParser.ShouldParseBody(method, false)).IsTrue();
}
}
}