mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-18 23:20:11 +02:00
Fix issue with application/x-www-form-urlencoded and ExactMatcher (#907)
This commit is contained in:
@@ -28,7 +28,7 @@ internal static class HttpRequestMessageHelper
|
|||||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.Bytes:
|
case BodyType.Bytes:
|
||||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes, contentType);
|
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
@@ -36,7 +36,8 @@ internal static class HttpRequestMessageHelper
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString, contentType);
|
case BodyType.FormUrlEncoded:
|
||||||
|
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,6 +157,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
{
|
{
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||||
|
|
||||||
case BodyType.Bytes:
|
case BodyType.Bytes:
|
||||||
@@ -171,7 +172,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
{
|
{
|
||||||
// If the body is a byte array, try to match.
|
// If the body is a byte array, try to match.
|
||||||
var detectedBodyType = requestMessage.BodyData?.DetectedBodyType;
|
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);
|
return exactObjectMatcher.IsMatch(requestMessage.BodyData?.BodyAsBytes);
|
||||||
}
|
}
|
||||||
@@ -197,7 +198,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
if (matcher is IStringMatcher stringMatcher)
|
if (matcher is IStringMatcher stringMatcher)
|
||||||
{
|
{
|
||||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
// 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);
|
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
switch (responseMessage.BodyData?.DetectedBodyType)
|
switch (responseMessage.BodyData?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
||||||
|
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ internal class LogEntryMapper
|
|||||||
switch (logEntry.RequestMessage.BodyData.DetectedBodyType)
|
switch (logEntry.RequestMessage.BodyData.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
logRequestModel.Body = logEntry.RequestMessage.BodyData.BodyAsString;
|
logRequestModel.Body = logEntry.RequestMessage.BodyData.BodyAsString;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -120,6 +121,7 @@ internal class LogEntryMapper
|
|||||||
switch (logEntry.ResponseMessage.BodyData!.DetectedBodyType)
|
switch (logEntry.ResponseMessage.BodyData!.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
if (!string.IsNullOrEmpty(logEntry.ResponseMessage.BodyData.IsFuncUsed) && _options.DoNotSaveDynamicResponseInLogEntry == true)
|
if (!string.IsNullOrEmpty(logEntry.ResponseMessage.BodyData.IsFuncUsed) && _options.DoNotSaveDynamicResponseInLogEntry == true)
|
||||||
{
|
{
|
||||||
logResponseModel.Body = logEntry.ResponseMessage.BodyData.IsFuncUsed;
|
logResponseModel.Body = logEntry.ResponseMessage.BodyData.IsFuncUsed;
|
||||||
@@ -142,6 +144,9 @@ internal class LogEntryMapper
|
|||||||
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
||||||
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ internal class MappingConverter
|
|||||||
switch (response.ResponseMessage.BodyData.DetectedBodyType)
|
switch (response.ResponseMessage.BodyData.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
sb.AppendLine($" .WithBody(\"{response.ResponseMessage.BodyData.BodyAsString}\")");
|
sb.AppendLine($" .WithBody(\"{response.ResponseMessage.BodyData.BodyAsString}\")");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -325,6 +326,7 @@ internal class MappingConverter
|
|||||||
switch (response.ResponseMessage.BodyData?.DetectedBodyType)
|
switch (response.ResponseMessage.BodyData?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
mappingModel.Response.Body = response.ResponseMessage.BodyData.BodyAsString;
|
mappingModel.Response.Body = response.ResponseMessage.BodyData.BodyAsString;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ internal class ProxyMappingConverter
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, true, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString!));
|
newRequest.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, true, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString!));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ internal static class WebhookMapper
|
|||||||
switch (webhook.Request.BodyData.DetectedBodyType)
|
switch (webhook.Request.BodyData.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
model.Request.Body = webhook.Request.BodyData.BodyAsString;
|
model.Request.Body = webhook.Request.BodyData.BodyAsString;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -767,14 +767,18 @@ public partial class WireMockServer
|
|||||||
|
|
||||||
private static T DeserializeObject<T>(IRequestMessage requestMessage) where T : new()
|
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)
|
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.DetectedBodyType = BodyType.String;
|
||||||
response.BodyData.BodyAsString = encoding.GetString(bytes);
|
response.BodyData.BodyAsString = encoding.GetString(bytes);
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ internal class Transformer : ITransformer
|
|||||||
{
|
{
|
||||||
responseMessage.BodyData = TransformBodyData(transformerContext, options, model, original.BodyData, useTransformerForBodyAsFile);
|
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;
|
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)
|
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),
|
case BodyType.Json:
|
||||||
BodyType.File => TransformBodyAsFile(transformerContext, model, original, useTransformerForBodyAsFile),
|
return TransformBodyAsJson(transformerContext, options, model, original);
|
||||||
BodyType.String => TransformBodyAsString(transformerContext, model, original),
|
|
||||||
_ => null
|
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)
|
private static IDictionary<string, WireMockList<string>> TransformHeaders(ITransformerContext transformerContext, TransformModel model, IDictionary<string, WireMockList<string>>? original)
|
||||||
|
|||||||
@@ -94,6 +94,38 @@ public partial class WireMockServerTests
|
|||||||
|
|
||||||
server.Stop();
|
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
|
#endif
|
||||||
Reference in New Issue
Block a user