mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-14 15:43:33 +01:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dea577da1 | ||
|
|
7ca4294de6 | ||
|
|
66245409f9 | ||
|
|
da6cb9fe0a | ||
|
|
b30e4faab6 | ||
|
|
1221d52c69 |
11
CHANGELOG.md
11
CHANGELOG.md
@@ -1,7 +1,16 @@
|
||||
# 1.5.21 (22 March 2023)
|
||||
- [#908](https://github.com/WireMock-Net/WireMock.Net/pull/908) - RequestBuilder : add WithBodyAsJson and WithBody (with IJsonConverter) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#911](https://github.com/WireMock-Net/WireMock.Net/pull/911) - Fixed QueryStringParser for UrlEncoded values [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#901](https://github.com/WireMock-Net/WireMock.Net/issues/901) - Matching one form-urlencoded value [feature]
|
||||
|
||||
# 1.5.20 (19 March 2023)
|
||||
- [#905](https://github.com/WireMock-Net/WireMock.Net/pull/905) - Add DeserializeFormUrl Encoded to the settings [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#907](https://github.com/WireMock-Net/WireMock.Net/pull/907) - Fix issue with application/x-www-form-urlencoded and ExactMatcher [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#906](https://github.com/WireMock-Net/WireMock.Net/issues/906) - Upgrade to 1.5.19 breaks a form data test [bug]
|
||||
|
||||
# 1.5.19 (17 March 2023)
|
||||
- [#903](https://github.com/WireMock-Net/WireMock.Net/pull/903) - Add WithBody with IDictionary (form-urlencoded values) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#904](https://github.com/WireMock-Net/WireMock.Net/pull/904) - Update Handlebars.Net.Helpers to 2.3.15 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#901](https://github.com/WireMock-Net/WireMock.Net/issues/901) - Matching one form-urlencoded value [feature]
|
||||
|
||||
# 1.5.18 (09 March 2023)
|
||||
- [#893](https://github.com/WireMock-Net/WireMock.Net/pull/893) - Add 'Data' to response which can be used during transforming the response [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.5.19</VersionPrefix>
|
||||
<VersionPrefix>1.5.21</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.5.19
|
||||
SET version=1.5.21
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 1.5.19 (17 March 2023)
|
||||
- #903 Add WithBody with IDictionary (form-urlencoded values) [feature]
|
||||
- #904 Update Handlebars.Net.Helpers to 2.3.15 [feature]
|
||||
# 1.5.21 (22 March 2023)
|
||||
- #908 RequestBuilder : add WithBodyAsJson and WithBody (with IJsonConverter) [feature]
|
||||
- #911 Fixed QueryStringParser for UrlEncoded values [bug]
|
||||
- #901 Matching one form-urlencoded value [feature]
|
||||
|
||||
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
||||
@@ -31,27 +31,49 @@ public class SettingsModel
|
||||
public int? MaxRequestLogCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
||||
/// Allow a Body for all HTTP Methods. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handle all requests synchronously. (default set to false).
|
||||
/// Allow only a HttpStatus Code in the response which is defined. (default set to <c>false</c>).
|
||||
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
|
||||
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
|
||||
/// </summary>
|
||||
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true to disable Json deserialization when processing requests. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? DisableJsonBodyParsing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Disable support for GZip and Deflate request body decompression. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? DisableRequestBodyDecompressing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true to disable FormUrlEncoded deserializing when processing requests. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? DisableDeserializeFormUrlEncoded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handle all requests synchronously. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Throw an exception when the Matcher fails because of invalid input. (default set to false).
|
||||
/// Throw an exception when the Matcher fails because of invalid input. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Use the RegexExtended instead of the default <see cref="Regex"/>. (default set to true).
|
||||
/// Use the RegexExtended instead of the default <see cref="Regex"/>. (default set to <c>true</c>).
|
||||
/// </summary>
|
||||
public bool? UseRegexExtended { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/>. (default set to false).
|
||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/>. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? SaveUnmatchedRequests { get; set; }
|
||||
|
||||
@@ -86,7 +108,7 @@ public class SettingsModel
|
||||
public HostingScheme? HostingScheme { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ internal static class HttpRequestMessageHelper
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Bytes:
|
||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes, contentType);
|
||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType);
|
||||
break;
|
||||
|
||||
case BodyType.Json:
|
||||
@@ -36,7 +36,8 @@ internal static class HttpRequestMessageHelper
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString, contentType);
|
||||
case BodyType.FormUrlEncoded:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ internal static class HttpResponseMessageHelper
|
||||
Uri requiredUri,
|
||||
Uri originalUri,
|
||||
bool deserializeJson,
|
||||
bool decompressGzipAndDeflate)
|
||||
bool decompressGzipAndDeflate,
|
||||
bool deserializeFormUrlEncoded)
|
||||
{
|
||||
var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode };
|
||||
|
||||
@@ -44,7 +45,8 @@ internal static class HttpResponseMessageHelper
|
||||
ContentType = contentTypeHeader?.FirstOrDefault(),
|
||||
DeserializeJson = deserializeJson,
|
||||
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
|
||||
DecompressGZipAndDeflate = decompressGzipAndDeflate
|
||||
DecompressGZipAndDeflate = decompressGzipAndDeflate,
|
||||
DeserializeFormUrlEncoded = deserializeFormUrlEncoded
|
||||
};
|
||||
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||
}
|
||||
@@ -55,7 +57,7 @@ internal static class HttpResponseMessageHelper
|
||||
// If Location header contains absolute redirect URL, and base URL is one that we proxy to,
|
||||
// we need to replace it to original one.
|
||||
if (string.Equals(header.Key, HttpKnownHeaderNames.Location, StringComparison.OrdinalIgnoreCase)
|
||||
&& Uri.TryCreate(header.Value.First(), UriKind.Absolute, out Uri absoluteLocationUri)
|
||||
&& Uri.TryCreate(header.Value.First(), UriKind.Absolute, out var absoluteLocationUri)
|
||||
&& string.Equals(absoluteLocationUri.Host, requiredUri.Host, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var replacedLocationUri = new Uri(originalUri, absoluteLocationUri.PathAndQuery);
|
||||
|
||||
@@ -60,7 +60,7 @@ internal static class JObjectExtensions
|
||||
{
|
||||
if (src == null)
|
||||
{
|
||||
return new object?[0];
|
||||
return EmptyArray<object?>.Value;
|
||||
}
|
||||
|
||||
return ConvertJTokenArray(src, options);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using WireMock.Models;
|
||||
@@ -62,7 +63,7 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
return new AnyOf<string, StringPattern>[0];
|
||||
return EmptyArray<AnyOf<string, StringPattern>>.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -157,6 +157,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
{
|
||||
case BodyType.Json:
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||
|
||||
case BodyType.Bytes:
|
||||
@@ -171,7 +172,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
{
|
||||
// If the body is a byte array, try to match.
|
||||
var detectedBodyType = requestMessage.BodyData?.DetectedBodyType;
|
||||
if (detectedBodyType is BodyType.Bytes or BodyType.String)
|
||||
if (detectedBodyType is BodyType.Bytes or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return exactObjectMatcher.IsMatch(requestMessage.BodyData?.BodyAsBytes);
|
||||
}
|
||||
@@ -197,7 +198,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
||||
if (matcher is IStringMatcher stringMatcher)
|
||||
{
|
||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
||||
if (requestMessage?.BodyData?.DetectedBodyType is BodyType.Json or BodyType.String)
|
||||
if (requestMessage?.BodyData?.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||
}
|
||||
|
||||
@@ -130,6 +130,7 @@ namespace WireMock.Owin.Mappers
|
||||
switch (responseMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
||||
|
||||
case BodyType.Json:
|
||||
|
||||
@@ -45,8 +45,16 @@ internal class ProxyHelper
|
||||
// Create ResponseMessage
|
||||
bool deserializeJson = !_settings.DisableJsonBodyParsing.GetValueOrDefault(false);
|
||||
bool decompressGzipAndDeflate = !_settings.DisableRequestBodyDecompressing.GetValueOrDefault(false);
|
||||
bool deserializeFormUrlEncoded = !_settings.DisableDeserializeFormUrlEncoded.GetValueOrDefault(false);
|
||||
|
||||
var responseMessage = await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson, decompressGzipAndDeflate).ConfigureAwait(false);
|
||||
var responseMessage = await HttpResponseMessageHelper.CreateAsync(
|
||||
httpResponseMessage,
|
||||
requiredUri,
|
||||
originalUri,
|
||||
deserializeJson,
|
||||
decompressGzipAndDeflate,
|
||||
deserializeFormUrlEncoded
|
||||
).ConfigureAwait(false);
|
||||
|
||||
IMapping? newMapping = null;
|
||||
|
||||
@@ -56,11 +64,11 @@ internal class ProxyHelper
|
||||
if (saveMappingSettings != null)
|
||||
{
|
||||
save &= Check(saveMappingSettings.StatusCodePattern,
|
||||
() => HttpStatusRangeParser.IsMatch(saveMappingSettings.StatusCodePattern, responseMessage.StatusCode)
|
||||
() => saveMappingSettings.StatusCodePattern != null && HttpStatusRangeParser.IsMatch(saveMappingSettings.StatusCodePattern, responseMessage.StatusCode)
|
||||
);
|
||||
|
||||
save &= Check(saveMappingSettings.HttpMethods,
|
||||
() => saveMappingSettings.HttpMethods.Value.Contains(requestMessage.Method, StringComparer.OrdinalIgnoreCase)
|
||||
() => saveMappingSettings.HttpMethods != null && saveMappingSettings.HttpMethods.Value.Contains(requestMessage.Method, StringComparer.OrdinalIgnoreCase)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JsonConverter.Abstractions;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Util;
|
||||
@@ -46,10 +47,28 @@ public interface IBodyRequestBuilder : IRequestMatcher
|
||||
/// WithBody: Body as object
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
|
||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBody(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Body as a string response based on a object (which will be converted to a JSON string using NewtonSoft.Json).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
|
||||
/// <returns>A <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Body as a string response based on a object (which will be converted to a JSON string using the <see cref="IJsonConverter"/>).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="converter">The JsonConverter.</param>
|
||||
/// <param name="options">The <see cref="JsonConverterOptions"/> [optional].</param>
|
||||
/// <param name="matchBehaviour">The match behaviour [default is AcceptOnMatch].</param>
|
||||
/// <returns>A <see cref="IRequestBuilder"/>.</returns>
|
||||
IRequestBuilder WithBodyAsJson(object body, IJsonConverter converter, JsonConverterOptions? options = null, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody: func (string)
|
||||
/// </summary>
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using JsonConverter.Abstractions;
|
||||
using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Util;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.RequestBuilders;
|
||||
|
||||
@@ -32,6 +34,24 @@ public partial class Request
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
var bodyAsJsonString = JsonConvert.SerializeObject(body);
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, bodyAsJsonString));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBodyAsJson(object body, IJsonConverter converter, JsonConverterOptions? options = null, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
Guard.NotNull(converter);
|
||||
|
||||
var bodyAsJsonString = converter.Serialize(body, options);
|
||||
_requestMatchers.Add(new RequestMessageBodyMatcher(matchBehaviour, bodyAsJsonString));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestBuilder WithBody(IMatcher matcher)
|
||||
{
|
||||
|
||||
@@ -92,7 +92,7 @@ public interface IBodyResponseBuilder : IFaultResponseBuilder
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="converter">The JsonConverter.</param>
|
||||
/// <param name="options">The IJsonConverterOption [optional].</param>
|
||||
/// <param name="options">The <see cref="JsonConverterOptions"/> [optional].</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(object body, IJsonConverter converter, JsonConverterOptions? options = null);
|
||||
|
||||
@@ -102,7 +102,7 @@ public interface IBodyResponseBuilder : IFaultResponseBuilder
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="encoding">The body encoding, can be <c>null</c>.</param>
|
||||
/// <param name="converter">The JsonConverter.</param>
|
||||
/// <param name="options">The IJsonConverterOption [optional].</param>
|
||||
/// <param name="options">The <see cref="JsonConverterOptions"/> [optional].</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(object body, Encoding? encoding, IJsonConverter converter, JsonConverterOptions? options = null);
|
||||
}
|
||||
@@ -44,6 +44,7 @@ internal class LogEntryMapper
|
||||
switch (logEntry.RequestMessage.BodyData.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
logRequestModel.Body = logEntry.RequestMessage.BodyData.BodyAsString;
|
||||
break;
|
||||
|
||||
@@ -120,6 +121,7 @@ internal class LogEntryMapper
|
||||
switch (logEntry.ResponseMessage.BodyData!.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
if (!string.IsNullOrEmpty(logEntry.ResponseMessage.BodyData.IsFuncUsed) && _options.DoNotSaveDynamicResponseInLogEntry == true)
|
||||
{
|
||||
logResponseModel.Body = logEntry.ResponseMessage.BodyData.IsFuncUsed;
|
||||
@@ -142,6 +144,9 @@ internal class LogEntryMapper
|
||||
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
||||
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,7 @@ internal class MappingConverter
|
||||
switch (response.ResponseMessage.BodyData.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
sb.AppendLine($" .WithBody(\"{response.ResponseMessage.BodyData.BodyAsString}\")");
|
||||
break;
|
||||
}
|
||||
@@ -140,7 +141,7 @@ internal class MappingConverter
|
||||
{
|
||||
sb.AppendLine($" .WithDelay({response.Delay.Value.TotalMilliseconds})");
|
||||
}
|
||||
else if (response.MinimumDelayMilliseconds > 0 && response.MaximumDelayMilliseconds > 0)
|
||||
else if (response is { MinimumDelayMilliseconds: > 0, MaximumDelayMilliseconds: > 0 })
|
||||
{
|
||||
sb.AppendLine($" .WithRandomDelay({response.MinimumDelayMilliseconds}, {response.MaximumDelayMilliseconds})");
|
||||
}
|
||||
@@ -325,6 +326,7 @@ internal class MappingConverter
|
||||
switch (response.ResponseMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
mappingModel.Response.Body = response.ResponseMessage.BodyData.BodyAsString;
|
||||
break;
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ internal class ProxyMappingConverter
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, true, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString!));
|
||||
break;
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ internal static class WebhookMapper
|
||||
switch (webhook.Request.BodyData.DetectedBodyType)
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
model.Request.Body = webhook.Request.BodyData.BodyAsString;
|
||||
break;
|
||||
|
||||
|
||||
@@ -217,10 +217,17 @@ public partial class WireMockServer
|
||||
var model = new SettingsModel
|
||||
{
|
||||
AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods,
|
||||
AllowOnlyDefinedHttpStatusCodeInResponse = _settings.AllowOnlyDefinedHttpStatusCodeInResponse,
|
||||
AllowPartialMapping = _settings.AllowPartialMapping,
|
||||
DisableDeserializeFormUrlEncoded = _settings.DisableDeserializeFormUrlEncoded,
|
||||
DisableJsonBodyParsing = _settings.DisableJsonBodyParsing,
|
||||
DisableRequestBodyDecompressing = _settings.DisableRequestBodyDecompressing,
|
||||
DoNotSaveDynamicResponseInLogEntry = _settings.DoNotSaveDynamicResponseInLogEntry,
|
||||
GlobalProcessingDelay = (int?)_options.RequestProcessingDelay?.TotalMilliseconds,
|
||||
HandleRequestsSynchronously = _settings.HandleRequestsSynchronously,
|
||||
HostingScheme = _settings.HostingScheme,
|
||||
MaxRequestLogCount = _settings.MaxRequestLogCount,
|
||||
QueryParameterMultipleValueSupport = _settings.QueryParameterMultipleValueSupport,
|
||||
ReadStaticMappings = _settings.ReadStaticMappings,
|
||||
RequestLogExpirationDuration = _settings.RequestLogExpirationDuration,
|
||||
SaveUnmatchedRequests = _settings.SaveUnmatchedRequests,
|
||||
@@ -228,14 +235,11 @@ public partial class WireMockServer
|
||||
UseRegexExtended = _settings.UseRegexExtended,
|
||||
WatchStaticMappings = _settings.WatchStaticMappings,
|
||||
WatchStaticMappingsInSubdirectories = _settings.WatchStaticMappingsInSubdirectories,
|
||||
HostingScheme = _settings.HostingScheme,
|
||||
DoNotSaveDynamicResponseInLogEntry = _settings.DoNotSaveDynamicResponseInLogEntry,
|
||||
QueryParameterMultipleValueSupport = _settings.QueryParameterMultipleValueSupport,
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
CorsPolicyOptions = _settings.CorsPolicyOptions?.ToString(),
|
||||
AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate,
|
||||
ClientCertificateMode = _settings.ClientCertificateMode,
|
||||
AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate
|
||||
CorsPolicyOptions = _settings.CorsPolicyOptions?.ToString()
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -250,10 +254,16 @@ public partial class WireMockServer
|
||||
|
||||
// _settings
|
||||
_settings.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods;
|
||||
_settings.AllowOnlyDefinedHttpStatusCodeInResponse = settings.AllowOnlyDefinedHttpStatusCodeInResponse;
|
||||
_settings.AllowPartialMapping = settings.AllowPartialMapping;
|
||||
_settings.DisableDeserializeFormUrlEncoded = settings.DisableDeserializeFormUrlEncoded;
|
||||
_settings.DisableJsonBodyParsing = settings.DisableJsonBodyParsing;
|
||||
_settings.DisableRequestBodyDecompressing = settings.DisableRequestBodyDecompressing;
|
||||
_settings.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||
_settings.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
_settings.MaxRequestLogCount = settings.MaxRequestLogCount;
|
||||
_settings.ProxyAndRecordSettings = TinyMapperUtils.Instance.Map(settings.ProxyAndRecordSettings);
|
||||
_settings.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||
_settings.ReadStaticMappings = settings.ReadStaticMappings;
|
||||
_settings.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||
_settings.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||
@@ -261,8 +271,6 @@ public partial class WireMockServer
|
||||
_settings.UseRegexExtended = settings.UseRegexExtended;
|
||||
_settings.WatchStaticMappings = settings.WatchStaticMappings;
|
||||
_settings.WatchStaticMappingsInSubdirectories = settings.WatchStaticMappingsInSubdirectories;
|
||||
_settings.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||
_settings.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||
|
||||
InitSettings(_settings);
|
||||
|
||||
@@ -759,14 +767,18 @@ public partial class WireMockServer
|
||||
|
||||
private static T DeserializeObject<T>(IRequestMessage requestMessage) where T : new()
|
||||
{
|
||||
return requestMessage.BodyData?.DetectedBodyType switch
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
BodyType.String => JsonUtils.DeserializeObject<T>(requestMessage.BodyData.BodyAsString!),
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return JsonUtils.DeserializeObject<T>(requestMessage.BodyData.BodyAsString!);
|
||||
|
||||
BodyType.Json when requestMessage.BodyData?.BodyAsJson != null => ((JObject)requestMessage.BodyData.BodyAsJson).ToObject<T>()!,
|
||||
case BodyType.Json when requestMessage.BodyData?.BodyAsJson != null:
|
||||
return ((JObject)requestMessage.BodyData.BodyAsJson).ToObject<T>()!;
|
||||
|
||||
_ => throw new NotSupportedException()
|
||||
};
|
||||
default:
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
|
||||
|
||||
@@ -65,7 +65,7 @@ namespace WireMock.Server
|
||||
}
|
||||
};
|
||||
|
||||
if (BytesEncodingUtils.TryGetEncoding(bytes, out Encoding encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
|
||||
if (BytesEncodingUtils.TryGetEncoding(bytes, out var encoding) && FileBodyIsString.Select(x => x.Equals(encoding)).Any())
|
||||
{
|
||||
response.BodyData.DetectedBodyType = BodyType.String;
|
||||
response.BodyData.BodyAsString = encoding.GetString(bytes);
|
||||
|
||||
@@ -6,7 +6,7 @@ public class ProxySaveMappingSetting<T>
|
||||
{
|
||||
public MatchBehaviour MatchBehaviour { get; } = MatchBehaviour.AcceptOnMatch;
|
||||
|
||||
public T Value { get; private set; }
|
||||
public T Value { get; }
|
||||
|
||||
public ProxySaveMappingSetting(T value, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
@@ -14,7 +14,7 @@ public class ProxySaveMappingSetting<T>
|
||||
MatchBehaviour = matchBehaviour;
|
||||
}
|
||||
|
||||
public static implicit operator ProxySaveMappingSetting<T>(T value) => new ProxySaveMappingSetting<T>(value);
|
||||
public static implicit operator ProxySaveMappingSetting<T>(T value) => new(value);
|
||||
|
||||
public static implicit operator T(ProxySaveMappingSetting<T> @this) => @this.Value;
|
||||
}
|
||||
@@ -32,7 +32,7 @@ internal class SimpleCommandLineParser
|
||||
}
|
||||
else if (string.IsNullOrEmpty(currentName))
|
||||
{
|
||||
Arguments[arg] = new string[0];
|
||||
Arguments[arg] = EmptyArray<string>.Value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -182,13 +182,13 @@ public class WireMockServerSettings
|
||||
public bool? AllowCSharpCodeMatcher { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
||||
/// Allow a Body for all HTTP Methods. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Allow only a HttpStatus Code in the response which is defined. (default set to false).
|
||||
/// Allow only a HttpStatus Code in the response which is defined. (default set to <c>false</c>).
|
||||
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
|
||||
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
|
||||
/// </summary>
|
||||
@@ -196,25 +196,31 @@ public class WireMockServerSettings
|
||||
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Set to true to disable Json deserialization when processing requests. (default set to false).
|
||||
/// Set to true to disable Json deserialization when processing requests. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? DisableJsonBodyParsing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Disable support for GZip and Deflate request body decompression. (default set to false).
|
||||
/// Disable support for GZip and Deflate request body decompression. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? DisableRequestBodyDecompressing { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handle all requests synchronously. (default set to false).
|
||||
/// Set to true to disable FormUrlEncoded deserializing when processing requests. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? DisableDeserializeFormUrlEncoded { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Handle all requests synchronously. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Throw an exception when the <see cref="IMatcher"/> fails because of invalid input. (default set to false).
|
||||
/// Throw an exception when the <see cref="IMatcher"/> fails because of invalid input. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||
@@ -255,19 +261,19 @@ public class WireMockServerSettings
|
||||
public WebhookSettings? WebhookSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to true).
|
||||
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to <c>true</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? UseRegexExtended { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/> (default set to false).
|
||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/> (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? SaveUnmatchedRequests { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to <c>false</c>).
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||
|
||||
@@ -4,7 +4,6 @@ using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
@@ -47,6 +46,8 @@ public static class WireMockServerSettingsParser
|
||||
AllowOnlyDefinedHttpStatusCodeInResponse = parser.GetBoolValue("AllowOnlyDefinedHttpStatusCodeInResponse"),
|
||||
AllowPartialMapping = parser.GetBoolValue("AllowPartialMapping"),
|
||||
DisableJsonBodyParsing = parser.GetBoolValue("DisableJsonBodyParsing"),
|
||||
DisableRequestBodyDecompressing = parser.GetBoolValue(nameof(WireMockServerSettings.DisableRequestBodyDecompressing)),
|
||||
DisableDeserializeFormUrlEncoded = parser.GetBoolValue(nameof(WireMockServerSettings.DisableDeserializeFormUrlEncoded)),
|
||||
HandleRequestsSynchronously = parser.GetBoolValue("HandleRequestsSynchronously"),
|
||||
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
|
||||
ReadStaticMappings = parser.GetBoolValue("ReadStaticMappings"),
|
||||
|
||||
@@ -85,7 +85,7 @@ internal class Transformer : ITransformer
|
||||
{
|
||||
responseMessage.BodyData = TransformBodyData(transformerContext, options, model, original.BodyData, useTransformerForBodyAsFile);
|
||||
|
||||
if (original.BodyData.DetectedBodyType == BodyType.String)
|
||||
if (original.BodyData.DetectedBodyType is BodyType.String or BodyType.FormUrlEncoded)
|
||||
{
|
||||
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
||||
}
|
||||
@@ -123,13 +123,21 @@ internal class Transformer : ITransformer
|
||||
|
||||
private IBodyData? TransformBodyData(ITransformerContext transformerContext, ReplaceNodeOptions options, TransformModel model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||
{
|
||||
return original.DetectedBodyType switch
|
||||
switch (original.DetectedBodyType)
|
||||
{
|
||||
BodyType.Json => TransformBodyAsJson(transformerContext, options, model, original),
|
||||
BodyType.File => TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile),
|
||||
BodyType.String => TransformBodyAsString(transformerContext, model, original),
|
||||
_ => null
|
||||
};
|
||||
case BodyType.Json:
|
||||
return TransformBodyAsJson(transformerContext, options, model, original);
|
||||
|
||||
case BodyType.File:
|
||||
return TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile);
|
||||
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return TransformBodyAsString(transformerContext, model, original);
|
||||
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, TransformModel model, IDictionary<string, WireMockList<string>>? original)
|
||||
|
||||
@@ -16,18 +16,14 @@ internal static class HttpStatusRangeParser
|
||||
/// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param>
|
||||
/// <param name="httpStatusCode">The value.</param>
|
||||
/// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception>
|
||||
public static bool IsMatch(string pattern, object? httpStatusCode)
|
||||
public static bool IsMatch(string? pattern, object? httpStatusCode)
|
||||
{
|
||||
switch (httpStatusCode)
|
||||
return httpStatusCode switch
|
||||
{
|
||||
case int statusCodeAsInteger:
|
||||
return IsMatch(pattern, statusCodeAsInteger);
|
||||
|
||||
case string statusCodeAsString:
|
||||
return IsMatch(pattern, int.Parse(statusCodeAsString));
|
||||
}
|
||||
|
||||
return false;
|
||||
int statusCodeAsInteger => IsMatch(pattern, statusCodeAsInteger),
|
||||
string statusCodeAsString => IsMatch(pattern, int.Parse(statusCodeAsString)),
|
||||
_ => false
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -32,7 +32,7 @@ internal static class QueryStringParser
|
||||
{
|
||||
if (part.Length == 2)
|
||||
{
|
||||
nameValueCollection.Add(part[0], part[1]);
|
||||
nameValueCollection.Add(part[0], WebUtility.UrlDecode(part[1]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,12 @@ internal static class RegexUtils
|
||||
{
|
||||
if (useRegexExtended)
|
||||
{
|
||||
var r = new RegexExtended(pattern, RegexOptions.None, RegexTimeOut);
|
||||
return (true, r.IsMatch(input));
|
||||
}
|
||||
else
|
||||
{
|
||||
var r = new Regex(pattern, RegexOptions.None, RegexTimeOut);
|
||||
return (true, r.IsMatch(input));
|
||||
var regexExtended = new RegexExtended(pattern, RegexOptions.None, RegexTimeOut);
|
||||
return (true, regexExtended.IsMatch(input));
|
||||
}
|
||||
|
||||
var regex = new Regex(pattern, RegexOptions.None, RegexTimeOut);
|
||||
return (true, regex.IsMatch(input));
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
/// <summary>
|
||||
/// Code based on https://stackoverflow.com/questions/40507909/convert-jobject-to-anonymous-object
|
||||
/// </summary>
|
||||
internal static class TypeBuilderUtils
|
||||
{
|
||||
private static readonly ConcurrentDictionary<IDictionary<string, Type>, Type> Types = new();
|
||||
|
||||
private static readonly ModuleBuilder ModuleBuilder = AssemblyBuilder
|
||||
.DefineDynamicAssembly(new AssemblyName("WireMock.Net.Reflection"), AssemblyBuilderAccess.Run)
|
||||
.DefineDynamicModule("WireMock.Net.Reflection.Module");
|
||||
|
||||
public static Type BuildType(IDictionary<string, Type> properties, string? name = null)
|
||||
{
|
||||
var keyExists = Types.Keys.FirstOrDefault(k => Compare(k, properties));
|
||||
if (keyExists != null)
|
||||
{
|
||||
return Types[keyExists];
|
||||
}
|
||||
|
||||
var typeBuilder = GetTypeBuilder(name ?? Guid.NewGuid().ToString());
|
||||
foreach (var property in properties)
|
||||
{
|
||||
CreateGetSetMethods(typeBuilder, property.Key, property.Value);
|
||||
}
|
||||
|
||||
var type = typeBuilder.CreateTypeInfo()!.AsType();
|
||||
|
||||
Types.TryAdd(properties, type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// https://stackoverflow.com/questions/3804367/testing-for-equality-between-dictionaries-in-c-sharp
|
||||
/// </summary>
|
||||
private static bool Compare<TKey, TValue>(IDictionary<TKey, TValue> dict1, IDictionary<TKey, TValue> dict2)
|
||||
where TKey : notnull
|
||||
{
|
||||
if (dict1 == dict2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (dict1.Count != dict2.Count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var valueComparer = EqualityComparer<TValue>.Default;
|
||||
|
||||
foreach (var kvp in dict1)
|
||||
{
|
||||
if (!dict2.TryGetValue(kvp.Key, out var value2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!valueComparer.Equals(kvp.Value, value2))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static TypeBuilder GetTypeBuilder(string name)
|
||||
{
|
||||
return ModuleBuilder.DefineType(name,
|
||||
TypeAttributes.Public |
|
||||
TypeAttributes.Class |
|
||||
TypeAttributes.AutoClass |
|
||||
TypeAttributes.AnsiClass |
|
||||
TypeAttributes.BeforeFieldInit |
|
||||
TypeAttributes.AutoLayout,
|
||||
null);
|
||||
}
|
||||
|
||||
private static void CreateGetSetMethods(TypeBuilder typeBuilder, string propertyName, Type propertyType)
|
||||
{
|
||||
var fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
|
||||
|
||||
var propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
|
||||
|
||||
var getPropertyMethodBuilder = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
|
||||
var getIl = getPropertyMethodBuilder.GetILGenerator();
|
||||
|
||||
getIl.Emit(OpCodes.Ldarg_0);
|
||||
getIl.Emit(OpCodes.Ldfld, fieldBuilder);
|
||||
getIl.Emit(OpCodes.Ret);
|
||||
|
||||
var setPropertyMethodBuilder = typeBuilder.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType });
|
||||
var setIl = setPropertyMethodBuilder.GetILGenerator();
|
||||
var modifyProperty = setIl.DefineLabel();
|
||||
|
||||
var exitSet = setIl.DefineLabel();
|
||||
|
||||
setIl.MarkLabel(modifyProperty);
|
||||
setIl.Emit(OpCodes.Ldarg_0);
|
||||
setIl.Emit(OpCodes.Ldarg_1);
|
||||
setIl.Emit(OpCodes.Stfld, fieldBuilder);
|
||||
|
||||
setIl.Emit(OpCodes.Nop);
|
||||
setIl.MarkLabel(exitSet);
|
||||
setIl.Emit(OpCodes.Ret);
|
||||
|
||||
propertyBuilder.SetGetMethod(getPropertyMethodBuilder);
|
||||
propertyBuilder.SetSetMethod(setPropertyMethodBuilder);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace WireMock.Validation
|
||||
{
|
||||
/// <summary>
|
||||
/// To fix 'xxx' is null on at least one execution path. See also https://rules.sonarsource.com/csharp/RSPEC-3900.
|
||||
/// </summary>
|
||||
internal class ValidatedNotNullAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
@@ -37,7 +38,7 @@ public class JmesPathMatcherTests
|
||||
public void JmesPathMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var bytes = EmptyArray<byte>.Value;
|
||||
var matcher = new JmesPathMatcher("");
|
||||
|
||||
// Act
|
||||
|
||||
@@ -111,7 +111,7 @@ public class JsonMatcherTests
|
||||
public void JsonMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var bytes = EmptyArray<byte>.Value;
|
||||
var matcher = new JsonMatcher("");
|
||||
|
||||
// Act
|
||||
|
||||
@@ -89,7 +89,7 @@ public class JsonPartialMatcherTests
|
||||
public void JsonPartialMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var bytes = EmptyArray<byte>.Value;
|
||||
var matcher = new JsonPartialMatcher("");
|
||||
|
||||
// Act
|
||||
|
||||
@@ -89,7 +89,7 @@ public class JsonPartialWildcardMatcherTests
|
||||
public void JsonPartialWildcardMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var bytes = EmptyArray<byte>.Value;
|
||||
var matcher = new JsonPartialWildcardMatcher("");
|
||||
|
||||
// Act
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
@@ -37,7 +38,7 @@ public class JsonPathMatcherTests
|
||||
public void JsonPathMatcher_IsMatch_ByteArray()
|
||||
{
|
||||
// Assign
|
||||
var bytes = new byte[0];
|
||||
var bytes = EmptyArray<byte>.Value;
|
||||
var matcher = new JsonPathMatcher("");
|
||||
|
||||
// Act
|
||||
|
||||
@@ -2,6 +2,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using JsonConverter.Abstractions;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NFluent;
|
||||
using WireMock.Matchers;
|
||||
@@ -134,7 +136,7 @@ namespace WireMock.Net.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_BodyAsString_Using_WildcardMatcher()
|
||||
public void Request_WithBody_BodyDataAsString_Using_WildcardMatcher()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().WithPath("/foo").UsingAnyMethod().WithBody(new WildcardMatcher("H*o*"));
|
||||
@@ -153,7 +155,7 @@ namespace WireMock.Net.Tests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_BodyAsJson_Using_WildcardMatcher()
|
||||
public void Request_WithBody_BodyDataAsJson_Using_WildcardMatcher()
|
||||
{
|
||||
// Arrange
|
||||
var spec = Request.Create().WithPath("/foo").UsingAnyMethod().WithBody(new WildcardMatcher("*Hello*"));
|
||||
@@ -349,6 +351,56 @@ namespace WireMock.Net.Tests
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_UsingObject()
|
||||
{
|
||||
// Assign
|
||||
object body = new
|
||||
{
|
||||
Test = "abc"
|
||||
};
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBodyAsJson(body);
|
||||
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsString = JsonConvert.SerializeObject(body),
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
// Act
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Request_WithBodyAsJson_WithIJsonConverter_UsingObject()
|
||||
{
|
||||
// Assign
|
||||
var jsonConverterMock = new Mock<IJsonConverter>();
|
||||
jsonConverterMock.Setup(j => j.Serialize(It.IsAny<object>(), It.IsAny<JsonConverterOptions>())).Returns("test");
|
||||
object body = new
|
||||
{
|
||||
Any = "key"
|
||||
};
|
||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBodyAsJson(body, jsonConverterMock.Object);
|
||||
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsString = "test",
|
||||
DetectedBodyType = BodyType.String
|
||||
};
|
||||
|
||||
// Act
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
|
||||
|
||||
// Assert
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(new byte[] { 1 }, BodyType.Bytes)]
|
||||
[InlineData(new byte[] { 48, 49, 50 }, BodyType.Bytes)]
|
||||
|
||||
@@ -38,6 +38,21 @@ public class QueryStringParserTests
|
||||
actual.Should().BeEquivalentTo(expectedOutput);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryParse_Should_Parse_QueryStringWithUrlEncodedValues()
|
||||
{
|
||||
// Arrange
|
||||
var key = "x";
|
||||
var value = "rNaCP7hv8UOmS%2FJcujdvLw%3D%3D";
|
||||
|
||||
// Act
|
||||
var result = QueryStringParser.TryParse($"{key}={value}", true, out var actual);
|
||||
|
||||
// Assert
|
||||
result.Should().BeTrue();
|
||||
actual.Should().BeEquivalentTo(new Dictionary<string, string> { { "x", "rNaCP7hv8UOmS/JcujdvLw==" } });
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_WithNullString()
|
||||
{
|
||||
|
||||
@@ -94,6 +94,38 @@ public partial class WireMockServerTests
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithExactMatcher()
|
||||
{
|
||||
// Arrange
|
||||
var server = WireMockServer.Start();
|
||||
server.Given(
|
||||
Request.Create()
|
||||
.UsingPost()
|
||||
.WithPath("/foo")
|
||||
.WithHeader("Content-Type", "application/x-www-form-urlencoded")
|
||||
.WithBody(new ExactMatcher("name=John+Doe&email=johndoe%40example.com")
|
||||
)
|
||||
)
|
||||
.RespondWith(
|
||||
Response.Create()
|
||||
);
|
||||
|
||||
// Act
|
||||
var content = new FormUrlEncodedContent(new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("name", "John Doe"),
|
||||
new KeyValuePair<string, string>("email", "johndoe@example.com")
|
||||
});
|
||||
var response = await new HttpClient()
|
||||
.PostAsync($"{server.Url}/foo", content)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user