mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-24 01:08:28 +02:00
Fix WithBody when using Pact and added more nullable annotations (#783)
* More nullable annotations * . * . * FIX * pact * . * p * xxx * ... * auth * array * ...
This commit is contained in:
@@ -1,28 +1,27 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the BodyDestinationFormat
|
||||
/// </summary>
|
||||
public static class BodyDestinationFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the BodyDestinationFormat
|
||||
/// Same as source (no conversion)
|
||||
/// </summary>
|
||||
public static class BodyDestinationFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// Same as source (no conversion)
|
||||
/// </summary>
|
||||
public const string SameAsSource = "SameAsSource";
|
||||
public const string SameAsSource = "SameAsSource";
|
||||
|
||||
/// <summary>
|
||||
/// Convert to string
|
||||
/// </summary>
|
||||
public const string String = "String";
|
||||
/// <summary>
|
||||
/// Convert to string
|
||||
/// </summary>
|
||||
public const string String = "String";
|
||||
|
||||
/// <summary>
|
||||
/// Convert to bytes
|
||||
/// </summary>
|
||||
public const string Bytes = "Bytes";
|
||||
/// <summary>
|
||||
/// Convert to bytes
|
||||
/// </summary>
|
||||
public const string Bytes = "Bytes";
|
||||
|
||||
/// <summary>
|
||||
/// Convert to Json object
|
||||
/// </summary>
|
||||
public const string Json = "Json";
|
||||
}
|
||||
/// <summary>
|
||||
/// Convert to Json object
|
||||
/// </summary>
|
||||
public const string Json = "Json";
|
||||
}
|
||||
@@ -2,72 +2,71 @@ using System;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The BodyResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IBodyResponseBuilder : IFaultResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The BodyResponseBuilder interface.
|
||||
/// WithBody : Create a ... response based on a string.
|
||||
/// </summary>
|
||||
public interface IBodyResponseBuilder : IFaultResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a string.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(string body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(string body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a callback function.
|
||||
/// </summary>
|
||||
/// <param name="bodyFactory">The delegate to build the body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a callback function.
|
||||
/// </summary>
|
||||
/// <param name="bodyFactory">The delegate to build the body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a callback function.
|
||||
/// </summary>
|
||||
/// <param name="bodyFactory">The async delegate to build the body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a callback function.
|
||||
/// </summary>
|
||||
/// <param name="bodyFactory">The async delegate to build the body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a bytearray.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(byte[] body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
/// <summary>
|
||||
/// WithBody : Create a ... response based on a bytearray.
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBody(byte[] body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Create a string response based on a object (which will be converted to a JSON string).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <param name="indented">Use JSON indented.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyAsJson(object body, Encoding? encoding = null, bool? indented = null);
|
||||
/// <summary>
|
||||
/// WithBody : Create a string response based on a object (which will be converted to a JSON string).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="encoding">The body encoding.</param>
|
||||
/// <param name="indented">Use JSON indented.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyAsJson(object body, Encoding? encoding = null, bool? indented = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithBody : Create a string response based on a object (which will be converted to a JSON string).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="indented">Define whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyAsJson(object body, bool indented);
|
||||
/// <summary>
|
||||
/// WithBody : Create a string response based on a object (which will be converted to a JSON string).
|
||||
/// </summary>
|
||||
/// <param name="body">The body.</param>
|
||||
/// <param name="indented">Define whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyAsJson(object body, bool indented);
|
||||
|
||||
/// <summary>
|
||||
/// WithBodyFromFile : Create a ... response based on a File.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <param name="cache">Defines if this file is cached in memory or retrieved from disk every time the response is created.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyFromFile(string filename, bool cache = true);
|
||||
}
|
||||
/// <summary>
|
||||
/// WithBodyFromFile : Create a ... response based on a File.
|
||||
/// </summary>
|
||||
/// <param name="filename">The filename.</param>
|
||||
/// <param name="cache">Defines if this file is cached in memory or retrieved from disk every time the response is created.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithBodyFromFile(string filename, bool cache = true);
|
||||
}
|
||||
@@ -3,25 +3,24 @@ using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.ResponseProviders;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The CallbackResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface ICallbackResponseBuilder : IResponseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The CallbackResponseBuilder interface.
|
||||
/// The callback builder
|
||||
/// </summary>
|
||||
public interface ICallbackResponseBuilder : IResponseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<IRequestMessage, ResponseMessage> callbackHandler);
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler);
|
||||
|
||||
/// <summary>
|
||||
/// The async callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<IRequestMessage, Task<ResponseMessage>> callbackHandler);
|
||||
}
|
||||
/// <summary>
|
||||
/// The async callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler);
|
||||
}
|
||||
@@ -1,32 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The DelayResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IDelayResponseBuilder : ICallbackResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The DelayResponseBuilder interface.
|
||||
/// The delay defined as a <see cref="TimeSpan"/>.
|
||||
/// </summary>
|
||||
public interface IDelayResponseBuilder : ICallbackResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The delay defined as a <see cref="TimeSpan"/>.
|
||||
/// </summary>
|
||||
/// <param name="delay">The TimeSpan to delay.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithDelay(TimeSpan delay);
|
||||
/// <param name="delay">The TimeSpan to delay.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithDelay(TimeSpan delay);
|
||||
|
||||
/// <summary>
|
||||
/// The delay defined as milliseconds.
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">The milliseconds to delay.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithDelay(int milliseconds);
|
||||
/// <summary>
|
||||
/// The delay defined as milliseconds.
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">The milliseconds to delay.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithDelay(int milliseconds);
|
||||
|
||||
/// <summary>
|
||||
/// Introduce random delay
|
||||
/// </summary>
|
||||
/// <param name="minimumMilliseconds">Minimum milliseconds to delay</param>
|
||||
/// <param name="maximumMilliseconds">Maximum milliseconds to delay</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000);
|
||||
}
|
||||
/// <summary>
|
||||
/// Introduce random delay
|
||||
/// </summary>
|
||||
/// <param name="minimumMilliseconds">Minimum milliseconds to delay</param>
|
||||
/// <param name="maximumMilliseconds">Maximum milliseconds to delay</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000);
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
using JetBrains.Annotations;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The FaultRequestBuilder interface.
|
||||
/// </summary>
|
||||
public interface IFaultResponseBuilder : ITransformResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The FaultRequestBuilder interface.
|
||||
/// WithBody : Create a fault response.
|
||||
/// </summary>
|
||||
public interface IFaultResponseBuilder : ITransformResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithBody : Create a fault response.
|
||||
/// </summary>
|
||||
/// <param name="faultType">The FaultType.</param>
|
||||
/// <param name="percentage">The percentage when this fault should occur. When null, it's always a fault.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithFault(FaultType faultType, [CanBeNull] double? percentage = null);
|
||||
}
|
||||
/// <param name="faultType">The FaultType.</param>
|
||||
/// <param name="percentage">The percentage when this fault should occur. When null, it's always a fault.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithFault(FaultType faultType, double? percentage = null);
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using JetBrains.Annotations;
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Types;
|
||||
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The ProxyResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IProxyResponseBuilder : IStatusCodeResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The ProxyResponseBuilder interface.
|
||||
/// WithProxy URL using Client X509Certificate2.
|
||||
/// </summary>
|
||||
public interface IProxyResponseBuilder : IStatusCodeResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// WithProxy URL using Client X509Certificate2.
|
||||
/// </summary>
|
||||
/// <param name="proxyUrl">The proxy url.</param>
|
||||
/// <param name="clientX509Certificate2ThumbprintOrSubjectName">The X509Certificate2 file to use for client authentication.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithProxy([NotNull] string proxyUrl, [CanBeNull] string clientX509Certificate2ThumbprintOrSubjectName = null);
|
||||
/// <param name="proxyUrl">The proxy url.</param>
|
||||
/// <param name="clientX509Certificate2ThumbprintOrSubjectName">The X509Certificate2 file to use for client authentication.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithProxy(string proxyUrl, string? clientX509Certificate2ThumbprintOrSubjectName = null);
|
||||
|
||||
/// <summary>
|
||||
/// WithProxy using IProxyAndRecordSettings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The IProxyAndRecordSettings.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithProxy([NotNull] ProxyAndRecordSettings settings);
|
||||
}
|
||||
/// <summary>
|
||||
/// WithProxy using IProxyAndRecordSettings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The IProxyAndRecordSettings.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithProxy([NotNull] ProxyAndRecordSettings settings);
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The ResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IResponseBuilder : IProxyResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The ResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IResponseBuilder : IProxyResponseBuilder
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,46 @@
|
||||
using System.Net;
|
||||
using System.Net;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The StatusCodeResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface IStatusCodeResponseBuilder : IHeadersResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The StatusCodeResponseBuilder interface.
|
||||
/// The with status code.
|
||||
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
|
||||
/// </summary>
|
||||
public interface IStatusCodeResponseBuilder : IHeadersResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The with status code.
|
||||
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithStatusCode(int code);
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithStatusCode(int code);
|
||||
|
||||
/// <summary>
|
||||
/// The with status code.
|
||||
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithStatusCode(string code);
|
||||
/// <summary>
|
||||
/// The with status code.
|
||||
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithStatusCode(string code);
|
||||
|
||||
/// <summary>
|
||||
/// The with status code.
|
||||
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithStatusCode(HttpStatusCode code);
|
||||
/// <summary>
|
||||
/// The with status code.
|
||||
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="code">The code.</param>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithStatusCode(HttpStatusCode code);
|
||||
|
||||
/// <summary>
|
||||
/// The with Success status code (200).
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithSuccess();
|
||||
/// <summary>
|
||||
/// The with Success status code (200).
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithSuccess();
|
||||
|
||||
/// <summary>
|
||||
/// The with NotFound status code (404).
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithNotFound();
|
||||
}
|
||||
/// <summary>
|
||||
/// The with NotFound status code (404).
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
IResponseBuilder WithNotFound();
|
||||
}
|
||||
@@ -1,34 +1,33 @@
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The TransformResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface ITransformResponseBuilder : IDelayResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// The TransformResponseBuilder interface.
|
||||
/// Use the Handlebars.Net ResponseMessage transformer.
|
||||
/// </summary>
|
||||
public interface ITransformResponseBuilder : IDelayResponseBuilder
|
||||
{
|
||||
/// <summary>
|
||||
/// Use the Handlebars.Net ResponseMessage transformer.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IResponseBuilder"/>.
|
||||
/// </returns>
|
||||
IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile);
|
||||
/// <returns>
|
||||
/// The <see cref="IResponseBuilder"/>.
|
||||
/// </returns>
|
||||
IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile);
|
||||
|
||||
/// <summary>
|
||||
/// Use the Handlebars.Net ResponseMessage transformer.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IResponseBuilder"/>.
|
||||
/// </returns>
|
||||
IResponseBuilder WithTransformer(ReplaceNodeOptions options);
|
||||
/// <summary>
|
||||
/// Use the Handlebars.Net ResponseMessage transformer.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IResponseBuilder"/>.
|
||||
/// </returns>
|
||||
IResponseBuilder WithTransformer(ReplaceNodeOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Use a specific ResponseMessage transformer.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IResponseBuilder"/>.
|
||||
/// </returns>
|
||||
IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None);
|
||||
}
|
||||
/// <summary>
|
||||
/// Use a specific ResponseMessage transformer.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IResponseBuilder"/>.
|
||||
/// </returns>
|
||||
IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None);
|
||||
}
|
||||
@@ -1,60 +1,62 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
public partial class Response
|
||||
{
|
||||
public partial class Response
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response.
|
||||
/// </summary>
|
||||
[MemberNotNullWhen(true, nameof(WithCallbackUsed))]
|
||||
public Func<IRequestMessage, ResponseMessage>? Callback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response async.
|
||||
/// </summary>
|
||||
[MemberNotNullWhen(true, nameof(WithCallbackUsed))]
|
||||
public Func<IRequestMessage, Task<ResponseMessage>>? CallbackAsync { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the method WithCallback(...) is used.
|
||||
/// </summary>
|
||||
public bool WithCallbackUsed { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response.
|
||||
/// </summary>
|
||||
public Func<IRequestMessage, ResponseMessage> Callback { get; private set; }
|
||||
Guard.NotNull(callbackHandler);
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response async.
|
||||
/// </summary>
|
||||
public Func<IRequestMessage, Task<ResponseMessage>> CallbackAsync { get; private set; }
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the method WithCallback(...) is used.
|
||||
/// </summary>
|
||||
public bool WithCallbackUsed { get; private set; }
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
Callback = callbackHandler;
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler);
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
Callback = callbackHandler;
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
CallbackAsync = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Guard.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
CallbackAsync = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
public partial class Response
|
||||
{
|
||||
/// <inheritdoc cref="IFaultResponseBuilder.WithFault(FaultType, double?)"/>
|
||||
public IResponseBuilder WithFault(FaultType faultType, double? percentage = null)
|
||||
{
|
||||
ResponseMessage.FaultType = faultType;
|
||||
ResponseMessage.FaultPercentage = percentage;
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
return this;
|
||||
}
|
||||
public partial class Response
|
||||
{
|
||||
/// <inheritdoc cref="IFaultResponseBuilder.WithFault(FaultType, double?)"/>
|
||||
public IResponseBuilder WithFault(FaultType faultType, double? percentage = null)
|
||||
{
|
||||
ResponseMessage.FaultType = faultType;
|
||||
ResponseMessage.FaultPercentage = percentage;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace WireMock.ResponseBuilders;
|
||||
|
||||
public partial class Response
|
||||
{
|
||||
private HttpClient _httpClientForProxy;
|
||||
private HttpClient? _httpClientForProxy;
|
||||
|
||||
/// <summary>
|
||||
/// The WebProxy settings.
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
using WireMock.Proxy;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
using WireMock.Transformers.Handlebars;
|
||||
@@ -18,464 +17,464 @@ using WireMock.Transformers.Scriban;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
/// <summary>
|
||||
/// The Response.
|
||||
/// </summary>
|
||||
public partial class Response : IResponseBuilder
|
||||
{
|
||||
private static readonly ThreadLocal<Random> Random = new(() => new Random(DateTime.UtcNow.Millisecond));
|
||||
|
||||
private TimeSpan? _delay;
|
||||
|
||||
/// <summary>
|
||||
/// The Response.
|
||||
/// The minimum random delay in milliseconds.
|
||||
/// </summary>
|
||||
public partial class Response : IResponseBuilder
|
||||
public int? MinimumDelayMilliseconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum random delay in milliseconds.
|
||||
/// </summary>
|
||||
public int? MaximumDelayMilliseconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The delay
|
||||
/// </summary>
|
||||
public TimeSpan? Delay
|
||||
{
|
||||
private static readonly ThreadLocal<Random> Random = new ThreadLocal<Random>(() => new Random(DateTime.UtcNow.Millisecond));
|
||||
|
||||
private TimeSpan? _delay;
|
||||
|
||||
/// <summary>
|
||||
/// The minimum random delay in milliseconds.
|
||||
/// </summary>
|
||||
public int? MinimumDelayMilliseconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The maximum random delay in milliseconds.
|
||||
/// </summary>
|
||||
public int? MaximumDelayMilliseconds { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The delay
|
||||
/// </summary>
|
||||
public TimeSpan? Delay
|
||||
get
|
||||
{
|
||||
get
|
||||
if (MinimumDelayMilliseconds != null && MaximumDelayMilliseconds != null)
|
||||
{
|
||||
if (MinimumDelayMilliseconds != null && MaximumDelayMilliseconds != null)
|
||||
{
|
||||
return TimeSpan.FromMilliseconds(Random.Value.Next(MinimumDelayMilliseconds.Value, MaximumDelayMilliseconds.Value));
|
||||
}
|
||||
|
||||
return _delay;
|
||||
return TimeSpan.FromMilliseconds(Random.Value!.Next(MinimumDelayMilliseconds.Value, MaximumDelayMilliseconds.Value));
|
||||
}
|
||||
|
||||
private set => _delay = value;
|
||||
return _delay;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [use transformer].
|
||||
/// </summary>
|
||||
public bool UseTransformer { get; private set; }
|
||||
private set => _delay = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the transformer.
|
||||
/// </summary>
|
||||
public TransformerType TransformerType { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether [use transformer].
|
||||
/// </summary>
|
||||
public bool UseTransformer { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to use the Handlebars transformer for the content from the referenced BodyAsFile.
|
||||
/// </summary>
|
||||
public bool UseTransformerForBodyAsFile { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets the type of the transformer.
|
||||
/// </summary>
|
||||
public TransformerType TransformerType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ReplaceNodeOptions to use when transforming a JSON node.
|
||||
/// </summary>
|
||||
public ReplaceNodeOptions TransformerReplaceNodeOptions { get; private set; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether to use the Handlebars transformer for the content from the referenced BodyAsFile.
|
||||
/// </summary>
|
||||
public bool UseTransformerForBodyAsFile { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the response message.
|
||||
/// </summary>
|
||||
public ResponseMessage ResponseMessage { get; }
|
||||
/// <summary>
|
||||
/// Gets the ReplaceNodeOptions to use when transforming a JSON node.
|
||||
/// </summary>
|
||||
public ReplaceNodeOptions TransformerReplaceNodeOptions { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates this instance.
|
||||
/// </summary>
|
||||
/// <param name="responseMessage">ResponseMessage</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null)
|
||||
/// <summary>
|
||||
/// Gets the response message.
|
||||
/// </summary>
|
||||
public ResponseMessage ResponseMessage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates this instance.
|
||||
/// </summary>
|
||||
/// <param name="responseMessage">ResponseMessage</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static IResponseBuilder Create(ResponseMessage? responseMessage = null)
|
||||
{
|
||||
var message = responseMessage ?? new ResponseMessage();
|
||||
return new Response(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates this instance with the specified function.
|
||||
/// </summary>
|
||||
/// <param name="func">The callback function.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static IResponseBuilder Create(Func<ResponseMessage> func)
|
||||
{
|
||||
Guard.NotNull(func);
|
||||
|
||||
return new Response(func());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Response"/> class.
|
||||
/// </summary>
|
||||
/// <param name="responseMessage">
|
||||
/// The response.
|
||||
/// </param>
|
||||
private Response(ResponseMessage responseMessage)
|
||||
{
|
||||
ResponseMessage = responseMessage;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStatusCodeResponseBuilder.WithStatusCode(int)"/>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithStatusCode(int code)
|
||||
{
|
||||
ResponseMessage.StatusCode = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStatusCodeResponseBuilder.WithStatusCode(string)"/>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithStatusCode(string code)
|
||||
{
|
||||
ResponseMessage.StatusCode = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStatusCodeResponseBuilder.WithStatusCode(HttpStatusCode)"/>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithStatusCode(HttpStatusCode code)
|
||||
{
|
||||
return WithStatusCode((int)code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with Success status code (200).
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithSuccess()
|
||||
{
|
||||
return WithStatusCode((int)HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with NotFound status code (404).
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithNotFound()
|
||||
{
|
||||
return WithStatusCode((int)HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/>
|
||||
public IResponseBuilder WithHeader(string name, params string[] values)
|
||||
{
|
||||
Guard.NotNull(name);
|
||||
|
||||
ResponseMessage.AddHeader(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
|
||||
{
|
||||
Guard.NotNull(headers);
|
||||
|
||||
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers)
|
||||
{
|
||||
Guard.NotNull(headers);
|
||||
|
||||
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers)
|
||||
{
|
||||
Guard.NotNull(headers);
|
||||
|
||||
ResponseMessage.Headers = headers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
|
||||
{
|
||||
Guard.NotNull(bodyFactory, nameof(bodyFactory));
|
||||
|
||||
return WithCallbackInternal(true, req => new ResponseMessage
|
||||
{
|
||||
var message = responseMessage ?? new ResponseMessage();
|
||||
return new Response(message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates this instance with the specified function.
|
||||
/// </summary>
|
||||
/// <param name="func">The callback function.</param>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public static IResponseBuilder Create([NotNull] Func<ResponseMessage> func)
|
||||
{
|
||||
Guard.NotNull(func, nameof(func));
|
||||
|
||||
return new Response(func());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Response"/> class.
|
||||
/// </summary>
|
||||
/// <param name="responseMessage">
|
||||
/// The response.
|
||||
/// </param>
|
||||
private Response(ResponseMessage responseMessage)
|
||||
{
|
||||
ResponseMessage = responseMessage;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStatusCodeResponseBuilder.WithStatusCode(int)"/>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithStatusCode(int code)
|
||||
{
|
||||
ResponseMessage.StatusCode = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStatusCodeResponseBuilder.WithStatusCode(string)"/>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithStatusCode(string code)
|
||||
{
|
||||
ResponseMessage.StatusCode = code;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStatusCodeResponseBuilder.WithStatusCode(HttpStatusCode)"/>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithStatusCode(HttpStatusCode code)
|
||||
{
|
||||
return WithStatusCode((int)code);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with Success status code (200).
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithSuccess()
|
||||
{
|
||||
return WithStatusCode((int)HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The with NotFound status code (404).
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
public IResponseBuilder WithNotFound()
|
||||
{
|
||||
return WithStatusCode((int)HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/>
|
||||
public IResponseBuilder WithHeader(string name, params string[] values)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
|
||||
ResponseMessage.AddHeader(name, values);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
|
||||
{
|
||||
Guard.NotNull(headers, nameof(headers));
|
||||
|
||||
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers)
|
||||
{
|
||||
Guard.NotNull(headers, nameof(headers));
|
||||
|
||||
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/>
|
||||
public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers)
|
||||
{
|
||||
ResponseMessage.Headers = headers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
|
||||
{
|
||||
Guard.NotNull(bodyFactory, nameof(bodyFactory));
|
||||
|
||||
return WithCallbackInternal(true, req => new ResponseMessage
|
||||
BodyData = new BodyData
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = bodyFactory(req),
|
||||
Encoding = encoding ?? Encoding.UTF8
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
|
||||
{
|
||||
Guard.NotNull(bodyFactory, nameof(bodyFactory));
|
||||
|
||||
return WithCallbackInternal(true, async req => new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = await bodyFactory(req).ConfigureAwait(false),
|
||||
Encoding = encoding ?? Encoding.UTF8
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(byte[], string, Encoding)"/>
|
||||
public IResponseBuilder WithBody(byte[] body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
|
||||
{
|
||||
Guard.NotNull(body, nameof(body));
|
||||
|
||||
ResponseMessage.BodyDestination = destination;
|
||||
ResponseMessage.BodyData = new BodyData();
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case BodyDestinationFormat.String:
|
||||
var enc = encoding ?? Encoding.UTF8;
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.String;
|
||||
ResponseMessage.BodyData.BodyAsString = enc.GetString(body);
|
||||
ResponseMessage.BodyData.Encoding = enc;
|
||||
break;
|
||||
|
||||
default:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes = body;
|
||||
break;
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = bodyFactory(req),
|
||||
Encoding = encoding ?? Encoding.UTF8
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
|
||||
{
|
||||
Guard.NotNull(bodyFactory, nameof(bodyFactory));
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/>
|
||||
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
|
||||
return WithCallbackInternal(true, async req => new ResponseMessage
|
||||
{
|
||||
Guard.NotNull(filename, nameof(filename));
|
||||
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
BodyData = new BodyData
|
||||
{
|
||||
BodyAsFileIsCached = cache,
|
||||
BodyAsFile = filename
|
||||
};
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = await bodyFactory(req).ConfigureAwait(false),
|
||||
Encoding = encoding ?? Encoding.UTF8
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (cache && !UseTransformer)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(byte[] body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
|
||||
{
|
||||
Guard.NotNull(body);
|
||||
|
||||
ResponseMessage.BodyDestination = destination;
|
||||
ResponseMessage.BodyData = new BodyData();
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case BodyDestinationFormat.String:
|
||||
var enc = encoding ?? Encoding.UTF8;
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.String;
|
||||
ResponseMessage.BodyData.BodyAsString = enc.GetString(body);
|
||||
ResponseMessage.BodyData.Encoding = enc;
|
||||
break;
|
||||
|
||||
default:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes = body;
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/>
|
||||
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
|
||||
{
|
||||
Guard.NotNull(filename);
|
||||
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
{
|
||||
BodyAsFileIsCached = cache,
|
||||
BodyAsFile = filename
|
||||
};
|
||||
|
||||
if (cache && !UseTransformer)
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.File;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(string body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
|
||||
{
|
||||
Guard.NotNull(body);
|
||||
|
||||
encoding ??= Encoding.UTF8;
|
||||
|
||||
ResponseMessage.BodyDestination = destination;
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
{
|
||||
Encoding = encoding
|
||||
};
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case BodyDestinationFormat.Bytes:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes = encoding.GetBytes(body);
|
||||
break;
|
||||
|
||||
case BodyDestinationFormat.Json:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Json;
|
||||
ResponseMessage.BodyData.BodyAsJson = JsonUtils.DeserializeObject(body);
|
||||
break;
|
||||
|
||||
default:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.String;
|
||||
ResponseMessage.BodyData.BodyAsString = body;
|
||||
break;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson(object, Encoding, bool?)"/>
|
||||
public IResponseBuilder WithBodyAsJson(object body, Encoding? encoding = null, bool? indented = null)
|
||||
{
|
||||
Guard.NotNull(body);
|
||||
|
||||
ResponseMessage.BodyDestination = null;
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
{
|
||||
Encoding = encoding,
|
||||
DetectedBodyType = BodyType.Json,
|
||||
BodyAsJson = body,
|
||||
BodyAsJsonIndented = indented
|
||||
};
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson(object, bool)"/>
|
||||
public IResponseBuilder WithBodyAsJson(object body, bool indented)
|
||||
{
|
||||
return WithBodyAsJson(body, null, indented);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(bool)"/>
|
||||
public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(ReplaceNodeOptions)"/>
|
||||
public IResponseBuilder WithTransformer(ReplaceNodeOptions options)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, false, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None)
|
||||
{
|
||||
UseTransformer = true;
|
||||
TransformerType = transformerType;
|
||||
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
||||
TransformerReplaceNodeOptions = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithDelay(TimeSpan delay)
|
||||
{
|
||||
Guard.Condition(delay, d => d == Timeout.InfiniteTimeSpan || d > TimeSpan.Zero);
|
||||
|
||||
Delay = delay;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithDelay(int milliseconds)
|
||||
{
|
||||
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000)
|
||||
{
|
||||
Guard.Condition(minimumMilliseconds, min => min >= 0);
|
||||
Guard.Condition(maximumMilliseconds, max => max > minimumMilliseconds);
|
||||
|
||||
MinimumDelayMilliseconds = minimumMilliseconds;
|
||||
MaximumDelayMilliseconds = maximumMilliseconds;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
{
|
||||
Guard.NotNull(requestMessage);
|
||||
Guard.NotNull(settings);
|
||||
|
||||
if (Delay != null)
|
||||
{
|
||||
await Task.Delay(Delay.Value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (ProxyAndRecordSettings != null && _httpClientForProxy != null)
|
||||
{
|
||||
string RemoveFirstOccurrence(string source, string find)
|
||||
{
|
||||
int place = source.IndexOf(find, StringComparison.OrdinalIgnoreCase);
|
||||
return place >= 0 ? source.Remove(place, find.Length) : source;
|
||||
}
|
||||
|
||||
var requestUri = new Uri(requestMessage.Url);
|
||||
|
||||
// Build the proxy url and skip duplicates
|
||||
string extra = RemoveFirstOccurrence(requestUri.LocalPath.TrimEnd('/'), new Uri(ProxyAndRecordSettings.Url).LocalPath.TrimEnd('/'));
|
||||
requestMessage.ProxyUrl = ProxyAndRecordSettings.Url + extra + requestUri.Query;
|
||||
|
||||
var proxyHelper = new ProxyHelper(settings);
|
||||
|
||||
return await proxyHelper.SendAsync(
|
||||
ProxyAndRecordSettings,
|
||||
_httpClientForProxy,
|
||||
requestMessage,
|
||||
requestMessage.ProxyUrl
|
||||
).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
ResponseMessage responseMessage;
|
||||
if (!WithCallbackUsed)
|
||||
{
|
||||
responseMessage = ResponseMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Callback != null)
|
||||
{
|
||||
responseMessage = Callback(requestMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.File;
|
||||
responseMessage = await CallbackAsync!(requestMessage).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return this;
|
||||
// Copy StatusCode from ResponseMessage (if defined)
|
||||
if (ResponseMessage.StatusCode != null)
|
||||
{
|
||||
responseMessage.StatusCode = ResponseMessage.StatusCode;
|
||||
}
|
||||
|
||||
// Copy Headers from ResponseMessage (if defined)
|
||||
if (ResponseMessage.Headers?.Count > 0)
|
||||
{
|
||||
responseMessage.Headers = ResponseMessage.Headers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(string, string, Encoding)"/>
|
||||
public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
|
||||
if (UseTransformer)
|
||||
{
|
||||
Guard.NotNull(body, nameof(body));
|
||||
|
||||
encoding = encoding ?? Encoding.UTF8;
|
||||
|
||||
ResponseMessage.BodyDestination = destination;
|
||||
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
ITransformer responseMessageTransformer;
|
||||
switch (TransformerType)
|
||||
{
|
||||
Encoding = encoding
|
||||
};
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case BodyDestinationFormat.Bytes:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes = encoding.GetBytes(body);
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback);
|
||||
responseMessageTransformer = new Transformer(factoryHandlebars);
|
||||
break;
|
||||
|
||||
case BodyDestinationFormat.Json:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Json;
|
||||
ResponseMessage.BodyData.BodyAsJson = JsonUtils.DeserializeObject(body);
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, TransformerType);
|
||||
responseMessageTransformer = new Transformer(factoryDotLiquid);
|
||||
break;
|
||||
|
||||
default:
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.String;
|
||||
ResponseMessage.BodyData.BodyAsString = body;
|
||||
break;
|
||||
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
return this;
|
||||
return (responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson(object, Encoding, bool?)"/>
|
||||
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null, bool? indented = null)
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
||||
{
|
||||
Guard.NotNull(body, nameof(body));
|
||||
|
||||
ResponseMessage.BodyDestination = null;
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
{
|
||||
Encoding = encoding,
|
||||
DetectedBodyType = BodyType.Json,
|
||||
BodyAsJson = body,
|
||||
BodyAsJsonIndented = indented
|
||||
};
|
||||
|
||||
return this;
|
||||
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData!.BodyAsFile);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson(object, bool)"/>
|
||||
public IResponseBuilder WithBodyAsJson(object body, bool indented)
|
||||
{
|
||||
return WithBodyAsJson(body, null, indented);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(bool)"/>
|
||||
public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(ReplaceNodeOptions)"/>
|
||||
public IResponseBuilder WithTransformer(ReplaceNodeOptions options)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, false, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None)
|
||||
{
|
||||
UseTransformer = true;
|
||||
TransformerType = transformerType;
|
||||
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
||||
TransformerReplaceNodeOptions = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithDelay(TimeSpan delay)
|
||||
{
|
||||
Guard.Condition(delay, d => d == Timeout.InfiniteTimeSpan || d > TimeSpan.Zero);
|
||||
|
||||
Delay = delay;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithDelay(int milliseconds)
|
||||
{
|
||||
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000)
|
||||
{
|
||||
Guard.Condition(minimumMilliseconds, min => min >= 0);
|
||||
Guard.Condition(maximumMilliseconds, max => max > minimumMilliseconds);
|
||||
|
||||
MinimumDelayMilliseconds = minimumMilliseconds;
|
||||
MaximumDelayMilliseconds = maximumMilliseconds;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||
{
|
||||
Guard.NotNull(requestMessage, nameof(requestMessage));
|
||||
Guard.NotNull(settings, nameof(settings));
|
||||
|
||||
if (Delay != null)
|
||||
{
|
||||
await Task.Delay(Delay.Value).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (ProxyAndRecordSettings != null && _httpClientForProxy != null)
|
||||
{
|
||||
string RemoveFirstOccurrence(string source, string find)
|
||||
{
|
||||
int place = source.IndexOf(find, StringComparison.OrdinalIgnoreCase);
|
||||
return place >= 0 ? source.Remove(place, find.Length) : source;
|
||||
}
|
||||
|
||||
var requestUri = new Uri(requestMessage.Url);
|
||||
|
||||
// Build the proxy url and skip duplicates
|
||||
string extra = RemoveFirstOccurrence(requestUri.LocalPath.TrimEnd('/'), new Uri(ProxyAndRecordSettings.Url).LocalPath.TrimEnd('/'));
|
||||
requestMessage.ProxyUrl = ProxyAndRecordSettings.Url + extra + requestUri.Query;
|
||||
|
||||
var proxyHelper = new ProxyHelper(settings);
|
||||
|
||||
return await proxyHelper.SendAsync(
|
||||
ProxyAndRecordSettings,
|
||||
_httpClientForProxy,
|
||||
requestMessage,
|
||||
requestMessage.ProxyUrl
|
||||
).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
ResponseMessage responseMessage;
|
||||
if (!WithCallbackUsed)
|
||||
{
|
||||
responseMessage = ResponseMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Callback != null)
|
||||
{
|
||||
responseMessage = Callback(requestMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage = await CallbackAsync(requestMessage).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
// Copy StatusCode from ResponseMessage (if defined)
|
||||
if (ResponseMessage.StatusCode != null)
|
||||
{
|
||||
responseMessage.StatusCode = ResponseMessage.StatusCode;
|
||||
}
|
||||
|
||||
// Copy Headers from ResponseMessage (if defined)
|
||||
if (ResponseMessage.Headers?.Count > 0)
|
||||
{
|
||||
responseMessage.Headers = ResponseMessage.Headers;
|
||||
}
|
||||
}
|
||||
|
||||
if (UseTransformer)
|
||||
{
|
||||
ITransformer responseMessageTransformer;
|
||||
switch (TransformerType)
|
||||
{
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(settings.FileSystemHandler, settings.HandlebarsRegistrationCallback);
|
||||
responseMessageTransformer = new Transformer(factoryHandlebars);
|
||||
break;
|
||||
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(settings.FileSystemHandler, TransformerType);
|
||||
responseMessageTransformer = new Transformer(factoryDotLiquid);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
return (responseMessageTransformer.Transform(requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||
}
|
||||
|
||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
||||
{
|
||||
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
||||
}
|
||||
|
||||
return (responseMessage, null);
|
||||
}
|
||||
return (responseMessage, null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user