Initial support for converting the mappings to a Pact(flow) json file (#748)

* WithDescription

* WithConsumer / WithProvider

* x

* .

* .

* .

* .

* fix

* pact

* nullable

* ficx

* .

* fix
This commit is contained in:
Stef Heyenrath
2022-04-22 16:17:50 +02:00
committed by GitHub
parent b06b3c8e8b
commit a6ee2dacc7
93 changed files with 1876 additions and 1065 deletions

View File

@@ -1,31 +1,30 @@
using System.Collections.Generic;
using System.Collections.Generic;
namespace WireMock.Admin.Mappings
namespace WireMock.Admin.Mappings;
/// <summary>
/// Cookie Model
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class CookieModel
{
/// <summary>
/// Cookie Model
/// Gets or sets the name.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class CookieModel
{
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; }
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public IList<MatcherModel> Matchers { get; set; }
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public IList<MatcherModel>? Matchers { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Reject on match.
/// </summary>
public bool? RejectOnMatch { get; set; }
}
/// <summary>
/// Reject on match.
/// </summary>
public bool? RejectOnMatch { get; set; }
}

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
namespace WireMock.Admin.Mappings
{
@@ -11,12 +11,12 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; }
public string Name { get; set; } = null!;
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public IList<MatcherModel> Matchers { get; set; }
public IList<MatcherModel>? Matchers { get; set; }
/// <summary>
/// Gets or sets the ignore case.

View File

@@ -24,6 +24,11 @@ namespace WireMock.Admin.Mappings
/// </summary>
public string Title { get; set; }
/// <summary>
/// The description.
/// </summary>
public string Description { get; set; }
/// <summary>
/// The priority. (A low value means higher priority.)
/// </summary>

View File

@@ -1,24 +1,23 @@
namespace WireMock.Admin.Mappings
namespace WireMock.Admin.Mappings;
/// <summary>
/// Param Model
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class ParamModel
{
/// <summary>
/// Param Model
/// Gets or sets the name.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class ParamModel
{
/// <summary>
/// Gets or sets the name.
/// </summary>
public string Name { get; set; }
public string Name { get; set; } = null!;
/// <summary>
/// Defines if the key should be matched using case-ignore.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Defines if the key should be matched using case-ignore.
/// </summary>
public bool? IgnoreCase { get; set; }
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public MatcherModel[] Matchers { get; set; }
}
/// <summary>
/// Gets or sets the matchers.
/// </summary>
public MatcherModel[]? Matchers { get; set; }
}

View File

@@ -1,51 +1,50 @@
using System.Collections.Generic;
using System.Collections.Generic;
namespace WireMock.Admin.Mappings
namespace WireMock.Admin.Mappings;
/// <summary>
/// RequestModel
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class RequestModel
{
/// <summary>
/// RequestModel
/// Gets or sets the ClientIP. (Can be a string or a ClientIPModel)
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class RequestModel
{
/// <summary>
/// Gets or sets the ClientIP. (Can be a string or a ClientIPModel)
/// </summary>
public object ClientIP { get; set; }
public object? ClientIP { get; set; }
/// <summary>
/// Gets or sets the Path. (Can be a string or a PathModel)
/// </summary>
public object Path { get; set; }
/// <summary>
/// Gets or sets the Path. (Can be a string or a PathModel)
/// </summary>
public object? Path { get; set; }
/// <summary>
/// Gets or sets the Url. (Can be a string or a UrlModel)
/// </summary>
public object Url { get; set; }
/// <summary>
/// Gets or sets the Url. (Can be a string or a UrlModel)
/// </summary>
public object? Url { get; set; }
/// <summary>
/// The methods
/// </summary>
public string[] Methods { get; set; }
/// <summary>
/// The methods
/// </summary>
public string[]? Methods { get; set; }
/// <summary>
/// Gets or sets the Headers.
/// </summary>
public IList<HeaderModel> Headers { get; set; }
/// <summary>
/// Gets or sets the Headers.
/// </summary>
public IList<HeaderModel>? Headers { get; set; }
/// <summary>
/// Gets or sets the Cookies.
/// </summary>
public IList<CookieModel> Cookies { get; set; }
/// <summary>
/// Gets or sets the Cookies.
/// </summary>
public IList<CookieModel>? Cookies { get; set; }
/// <summary>
/// Gets or sets the Params.
/// </summary>
public IList<ParamModel> Params { get; set; }
/// <summary>
/// Gets or sets the Params.
/// </summary>
public IList<ParamModel>? Params { get; set; }
/// <summary>
/// Gets or sets the body.
/// </summary>
public BodyModel Body { get; set; }
}
/// <summary>
/// Gets or sets the body.
/// </summary>
public BodyModel? Body { get; set; }
}

View File

@@ -11,22 +11,22 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// Gets or sets the HTTP status.
/// </summary>
public object StatusCode { get; set; }
public object? StatusCode { get; set; }
/// <summary>
/// Gets or sets the body destination (SameAsSource, String or Bytes).
/// </summary>
public string BodyDestination { get; set; }
public string? BodyDestination { get; set; }
/// <summary>
/// Gets or sets the body.
/// </summary>
public string Body { get; set; }
public string? Body { get; set; }
/// <summary>
/// Gets or sets the body (as JSON object).
/// </summary>
public object BodyAsJson { get; set; }
public object? BodyAsJson { get; set; }
/// <summary>
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
@@ -36,12 +36,12 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// Gets or sets the body (as bytearray).
/// </summary>
public byte[] BodyAsBytes { get; set; }
public byte[]? BodyAsBytes { get; set; }
/// <summary>
/// Gets or sets the body as a file.
/// </summary>
public string BodyAsFile { get; set; }
public string? BodyAsFile { get; set; }
/// <summary>
/// Is the body as file cached?
@@ -51,7 +51,7 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// Gets or sets the body encoding.
/// </summary>
public EncodingModel BodyEncoding { get; set; }
public EncodingModel? BodyEncoding { get; set; }
/// <summary>
/// Use ResponseMessage Transformer.
@@ -61,7 +61,7 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// Gets the type of the transformer.
/// </summary>
public string TransformerType { get; set; }
public string? TransformerType { get; set; }
/// <summary>
/// Use the Handlebars transformer for the content from the referenced BodyAsFile.
@@ -71,17 +71,17 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// The ReplaceNodeOptions to use when transforming a JSON node.
/// </summary>
public string TransformerReplaceNodeOptions { get; set; }
public string? TransformerReplaceNodeOptions { get; set; }
/// <summary>
/// Gets or sets the headers.
/// </summary>
public IDictionary<string, object> Headers { get; set; }
public IDictionary<string, object>? Headers { get; set; }
/// <summary>
/// Gets or sets the Headers (Raw).
/// </summary>
public string HeadersRaw { get; set; }
public string? HeadersRaw { get; set; }
/// <summary>
/// Gets or sets the delay in milliseconds.
@@ -101,21 +101,21 @@ namespace WireMock.Admin.Mappings
/// <summary>
/// Gets or sets the Proxy URL.
/// </summary>
public string ProxyUrl { get; set; }
public string? ProxyUrl { get; set; }
/// <summary>
/// The client X509Certificate2 Thumbprint or SubjectName to use.
/// </summary>
public string X509Certificate2ThumbprintOrSubjectName { get; set; }
public string? X509Certificate2ThumbprintOrSubjectName { get; set; }
/// <summary>
/// Gets or sets the fault.
/// </summary>
public FaultModel Fault { get; set; }
public FaultModel? Fault { get; set; }
/// <summary>
/// Gets or sets the WebProxy settings.
/// </summary>
public WebProxyModel WebProxy { get; set; }
public WebProxyModel? WebProxy { get; set; }
}
}

View File

@@ -1,56 +1,54 @@
using System;
using System;
namespace WireMock.Admin.Requests
namespace WireMock.Admin.Requests;
/// <summary>
/// Request Log Model
/// </summary>
public class LogEntryModel
{
/// <summary>
/// Request Log Model
/// The unique identifier.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogEntryModel
{
/// <summary>
/// The unique identifier.
/// </summary>
public Guid Guid { get; set; }
public Guid Guid { get; set; }
/// <summary>
/// The request.
/// </summary>
public LogRequestModel Request { get; set; }
/// <summary>
/// The request.
/// </summary>
public LogRequestModel Request { get; set; }
/// <summary>
/// The response.
/// </summary>
public LogResponseModel Response { get; set; }
/// <summary>
/// The response.
/// </summary>
public LogResponseModel Response { get; set; }
/// <summary>
/// The mapping unique identifier.
/// </summary>
public Guid? MappingGuid { get; set; }
/// <summary>
/// The mapping unique identifier.
/// </summary>
public Guid? MappingGuid { get; set; }
/// <summary>
/// The mapping unique title.
/// </summary>
public string MappingTitle { get; set; }
/// <summary>
/// The mapping unique title.
/// </summary>
public string MappingTitle { get; set; }
/// <summary>
/// The request match result.
/// </summary>
public LogRequestMatchModel RequestMatchResult { get; set; }
/// <summary>
/// The request match result.
/// </summary>
public LogRequestMatchModel RequestMatchResult { get; set; }
/// <summary>
/// The partial mapping unique identifier.
/// </summary>
public Guid? PartialMappingGuid { get; set; }
/// <summary>
/// The partial mapping unique identifier.
/// </summary>
public Guid? PartialMappingGuid { get; set; }
/// <summary>
/// The partial mapping unique title.
/// </summary>
public string PartialMappingTitle { get; set; }
/// <summary>
/// The partial mapping unique title.
/// </summary>
public string PartialMappingTitle { get; set; }
/// <summary>
/// The partial request match result.
/// </summary>
public LogRequestMatchModel PartialRequestMatchResult { get; set; }
}
/// <summary>
/// The partial request match result.
/// </summary>
public LogRequestMatchModel PartialRequestMatchResult { get; set; }
}

View File

@@ -1,51 +1,49 @@
using System.Collections.Generic;
using System.Collections.Generic;
namespace WireMock.Admin.Requests
namespace WireMock.Admin.Requests;
/// <summary>
/// LogRequestMatchModel
/// </summary>
public class LogRequestMatchModel
{
/// <summary>
/// LogRequestMatchModel
/// Gets or sets the match-score.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogRequestMatchModel
{
/// <summary>
/// Gets or sets the match-score.
/// </summary>
/// <value>
/// The match-score.
/// </value>
public double TotalScore { get; set; }
/// <value>
/// The match-score.
/// </value>
public double TotalScore { get; set; }
/// <summary>
/// Gets or sets the total number of matches.
/// </summary>
/// <value>
/// The total number of matches.
/// </value>
public int TotalNumber { get; set; }
/// <summary>
/// Gets or sets the total number of matches.
/// </summary>
/// <value>
/// The total number of matches.
/// </value>
public int TotalNumber { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is perfect match.
/// </summary>
/// <value>
/// <c>true</c> if this instance is perfect match; otherwise, <c>false</c>.
/// </value>
public bool IsPerfectMatch { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this instance is perfect match.
/// </summary>
/// <value>
/// <c>true</c> if this instance is perfect match; otherwise, <c>false</c>.
/// </value>
public bool IsPerfectMatch { get; set; }
/// <summary>
/// Gets the match percentage.
/// </summary>
/// <value>
/// The match percentage.
/// </value>
public double AverageTotalScore { get; set; }
/// <summary>
/// Gets the match percentage.
/// </summary>
/// <value>
/// The match percentage.
/// </value>
public double AverageTotalScore { get; set; }
/// <summary>
/// Gets the match details.
/// </summary>
/// <value>
/// The match details.
/// </value>
public IList<object> MatchDetails { get; set; }
}
/// <summary>
/// Gets the match details.
/// </summary>
/// <value>
/// The match details.
/// </value>
public IList<object> MatchDetails { get; set; }
}

View File

@@ -1,109 +1,107 @@
using System;
using System;
using System.Collections.Generic;
using WireMock.Admin.Mappings;
using WireMock.Types;
namespace WireMock.Admin.Requests
namespace WireMock.Admin.Requests;
/// <summary>
/// RequestMessage Model
/// </summary>
public class LogRequestModel
{
/// <summary>
/// RequestMessage Model
/// The Client IP Address.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogRequestModel
{
/// <summary>
/// The Client IP Address.
/// </summary>
public string ClientIP { get; set; }
public string ClientIP { get; set; }
/// <summary>
/// The DateTime.
/// </summary>
public DateTime DateTime { get; set; }
/// <summary>
/// The DateTime.
/// </summary>
public DateTime DateTime { get; set; }
/// <summary>
/// The Path.
/// </summary>
public string Path { get; set; }
/// <summary>
/// The Path.
/// </summary>
public string Path { get; set; }
/// <summary>
/// The Absolute Path.
/// </summary>
public string AbsolutePath { get; set; }
/// <summary>
/// The Absolute Path.
/// </summary>
public string AbsolutePath { get; set; }
/// <summary>
/// Gets the url (relative).
/// </summary>
public string Url { get; set; }
/// <summary>
/// Gets the url (relative).
/// </summary>
public string Url { get; set; }
/// <summary>
/// The absolute URL.
/// </summary>
public string AbsoluteUrl { get; set; }
/// <summary>
/// The absolute URL.
/// </summary>
public string AbsoluteUrl { get; set; }
/// <summary>
/// The ProxyUrl (if a proxy is used).
/// </summary>
public string ProxyUrl { get; set; }
/// <summary>
/// The ProxyUrl (if a proxy is used).
/// </summary>
public string? ProxyUrl { get; set; }
/// <summary>
/// The query.
/// </summary>
public IDictionary<string, WireMockList<string>> Query { get; set; }
/// <summary>
/// The query.
/// </summary>
public IDictionary<string, WireMockList<string>>? Query { get; set; }
/// <summary>
/// The method.
/// </summary>
public string Method { get; set; }
/// <summary>
/// The method.
/// </summary>
public string Method { get; set; }
/// <summary>
/// The Headers.
/// </summary>
public IDictionary<string, WireMockList<string>> Headers { get; set; }
/// <summary>
/// The Headers.
/// </summary>
public IDictionary<string, WireMockList<string>>? Headers { get; set; }
/// <summary>
/// The Cookies.
/// </summary>
public IDictionary<string, string> Cookies { get; set; }
/// <summary>
/// The Cookies.
/// </summary>
public IDictionary<string, string>? Cookies { get; set; }
/// <summary>
/// The body (as string).
/// </summary>
public string Body { get; set; }
/// <summary>
/// The body (as string).
/// </summary>
public string? Body { get; set; }
/// <summary>
/// The body (as JSON object).
/// </summary>
public object BodyAsJson { get; set; }
/// <summary>
/// The body (as JSON object).
/// </summary>
public object? BodyAsJson { get; set; }
/// <summary>
/// The body (as bytearray).
/// </summary>
public byte[] BodyAsBytes { get; set; }
/// <summary>
/// The body (as bytearray).
/// </summary>
public byte[]? BodyAsBytes { get; set; }
/// <summary>
/// The body encoding.
/// </summary>
public EncodingModel BodyEncoding { get; set; }
/// <summary>
/// The body encoding.
/// </summary>
public EncodingModel? BodyEncoding { get; set; }
/// <summary>
/// The DetectedBodyType, valid values are:
///
/// - None
/// - String
/// - Json
/// - Bytes
/// </summary>
public string DetectedBodyType { get; set; }
/// <summary>
/// The DetectedBodyType, valid values are:
///
/// - None
/// - String
/// - Json
/// - Bytes
/// </summary>
public string? DetectedBodyType { get; set; }
/// <summary>
/// The DetectedBodyTypeFromContentType, valid values are:
///
/// - None
/// - String
/// - Json
/// - Bytes
/// </summary>
public string DetectedBodyTypeFromContentType { get; set; }
}
/// <summary>
/// The DetectedBodyTypeFromContentType, valid values are:
///
/// - None
/// - String
/// - Json
/// - Bytes
/// </summary>
public string? DetectedBodyTypeFromContentType { get; set; }
}

View File

@@ -1,83 +1,81 @@
using System.Collections.Generic;
using System.Collections.Generic;
using WireMock.Admin.Mappings;
using WireMock.Types;
namespace WireMock.Admin.Requests
namespace WireMock.Admin.Requests;
/// <summary>
/// Response MessageModel
/// </summary>
public class LogResponseModel
{
/// <summary>
/// Response MessageModel
/// Gets or sets the status code.
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class LogResponseModel
{
/// <summary>
/// Gets or sets the status code.
/// </summary>
public object StatusCode { get; set; } = 200;
public object? StatusCode { get; set; }
/// <summary>
/// Gets the headers.
/// </summary>
public IDictionary<string, WireMockList<string>> Headers { get; set; }
/// <summary>
/// Gets the headers.
/// </summary>
public IDictionary<string, WireMockList<string>>? Headers { get; set; }
/// <summary>
/// Gets or sets the body destination (SameAsSource, String or Bytes).
/// </summary>
public string BodyDestination { get; set; }
/// <summary>
/// Gets or sets the body destination (SameAsSource, String or Bytes).
/// </summary>
public string? BodyDestination { get; set; }
/// <summary>
/// The body (as string).
/// </summary>
public string Body { get; set; }
/// <summary>
/// The body (as string).
/// </summary>
public string? Body { get; set; }
/// <summary>
/// The body (as JSON object).
/// </summary>
public object BodyAsJson { get; set; }
/// <summary>
/// The body (as JSON object).
/// </summary>
public object? BodyAsJson { get; set; }
/// <summary>
/// The body (as bytearray).
/// </summary>
public byte[] BodyAsBytes { get; set; }
/// <summary>
/// The body (as bytearray).
/// </summary>
public byte[]? BodyAsBytes { get; set; }
/// <summary>
/// Gets or sets the body as file.
/// </summary>
public string BodyAsFile { get; set; }
/// <summary>
/// Gets or sets the body as file.
/// </summary>
public string? BodyAsFile { get; set; }
/// <summary>
/// Is the body as file cached?
/// </summary>
public bool? BodyAsFileIsCached { get; set; }
/// <summary>
/// Is the body as file cached?
/// </summary>
public bool? BodyAsFileIsCached { get; set; }
/// <summary>
/// Gets or sets the original body.
/// </summary>
public string BodyOriginal { get; set; }
/// <summary>
/// Gets or sets the original body.
/// </summary>
public string? BodyOriginal { get; set; }
/// <summary>
/// Gets or sets the body.
/// </summary>
public EncodingModel BodyEncoding { get; set; }
/// <summary>
/// Gets or sets the body.
/// </summary>
public EncodingModel? BodyEncoding { get; set; }
/// <summary>
/// The detected body type (detection based on body content).
/// </summary>
public BodyType DetectedBodyType { get; set; }
/// <summary>
/// The detected body type (detection based on body content).
/// </summary>
public BodyType? DetectedBodyType { get; set; }
/// <summary>
/// The detected body type (detection based on Content-Type).
/// </summary>
public BodyType DetectedBodyTypeFromContentType { get; set; }
/// <summary>
/// The detected body type (detection based on Content-Type).
/// </summary>
public BodyType? DetectedBodyTypeFromContentType { get; set; }
/// <summary>
/// The FaultType.
/// </summary>
public string FaultType { get; set; }
/// <summary>
/// The FaultType.
/// </summary>
public string? FaultType { get; set; }
/// <summary>
/// Gets or sets the Fault percentage.
/// </summary>
public double? FaultPercentage { get; set; }
}
/// <summary>
/// Gets or sets the Fault percentage.
/// </summary>
public double? FaultPercentage { get; set; }
}

View File

@@ -1,4 +1,4 @@
namespace WireMock.Admin.Scenarios
namespace WireMock.Admin.Scenarios
{
/// <summary>
/// ScenarioStateModel
@@ -14,7 +14,7 @@
/// <summary>
/// Gets or sets the NextState.
/// </summary>
public string NextState { get; set; }
public string? NextState { get; set; }
/// <summary>
/// Gets or sets a value indicating whether this <see cref="ScenarioStateModel"/> is started.

View File

@@ -1,59 +1,58 @@
using JetBrains.Annotations;
namespace WireMock.Admin.Settings;
[FluentBuilder.AutoGenerateBuilder]
public class ProxyAndRecordSettingsModel
namespace WireMock.Admin.Settings
{
/// <summary>
/// The clientCertificate thumbprint or subject name fragment to use.
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
/// </summary>
public string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
[FluentBuilder.AutoGenerateBuilder]
public class ProxyAndRecordSettingsModel
{
/// <summary>
/// The clientCertificate thumbprint or subject name fragment to use.
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
/// </summary>
public string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
public WebProxySettingsModel WebProxySettings { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
public WebProxySettingsModel WebProxySettings { get; set; }
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
public bool? AllowAutoRedirect { get; set; }
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
public bool? AllowAutoRedirect { get; set; }
/// <summary>
/// The URL to proxy.
/// </summary>
public string Url { get; set; }
/// <summary>
/// The URL to proxy.
/// </summary>
public string Url { get; set; }
/// <summary>
/// Save the mapping for each request/response to the internal Mappings.
/// </summary>
public bool SaveMapping { get; set; }
/// <summary>
/// Save the mapping for each request/response to the internal Mappings.
/// </summary>
public bool SaveMapping { get; set; }
/// <summary>
/// Save the mapping for each request/response also to a file. (Note that SaveMapping must also be set to true.)
/// </summary>
public bool SaveMappingToFile { get; set; }
/// <summary>
/// Save the mapping for each request/response also to a file. (Note that SaveMapping must also be set to true.)
/// </summary>
public bool SaveMappingToFile { get; set; }
/// <summary>
/// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.)
/// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported.
/// </summary>
public string SaveMappingForStatusCodePattern { get; set; } = "*";
/// <summary>
/// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.)
/// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported.
/// </summary>
public string SaveMappingForStatusCodePattern { get; set; } = "*";
/// <summary>
/// Defines a list from headers which will be excluded from the saved mappings.
/// </summary>
public string[] ExcludedHeaders { get; set; }
/// <summary>
/// Defines a list from headers which will be excluded from the saved mappings.
/// </summary>
public string[] ExcludedHeaders { get; set; }
/// <summary>
/// Defines a list of cookies which will be excluded from the saved mappings.
/// </summary>
public string[] ExcludedCookies { get; set; }
/// <summary>
/// Defines a list of cookies which will be excluded from the saved mappings.
/// </summary>
public string[] ExcludedCookies { get; set; }
/// <summary>
/// Prefer the Proxy Mapping over the saved Mapping (in case SaveMapping is set to <c>true</c>).
/// </summary>
// public bool PreferProxyMapping { get; set; }
/// <summary>
/// Prefer the Proxy Mapping over the saved Mapping (in case SaveMapping is set to <c>true</c>).
/// </summary>
// public bool PreferProxyMapping { get; set; }
}
}

View File

@@ -1,5 +1,4 @@
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using WireMock.Handlers;
namespace WireMock.Admin.Settings
@@ -73,11 +72,11 @@ namespace WireMock.Admin.Settings
/// <summary>
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
/// </summary>
public string CorsPolicyOptions { get; set; }
public string? CorsPolicyOptions { get; set; }
/// <summary>
/// The proxy and record settings.
/// </summary>
public ProxyAndRecordSettingsModel ProxyAndRecordSettings { get; set; }
public ProxyAndRecordSettingsModel? ProxyAndRecordSettings { get; set; }
}
}

View File

@@ -14,11 +14,11 @@ namespace WireMock.Admin.Settings
/// <summary>
/// The user name associated with the credentials.
/// </summary>
public string UserName { get; set; }
public string? UserName { get; set; }
/// <summary>
/// The password for the user name associated with the credentials.
/// </summary>
public string Password { get; set; }
public string? Password { get; set; }
}
}

View File

@@ -4,7 +4,7 @@ using System.Collections.Generic;
namespace WireMock.Handlers
{
/// <summary>
/// Handler to interact with the file system to handle folders and read and write static mapping files.
/// Handler to interact with the file system to handle folders and read and write (static mapping) files.
/// </summary>
public interface IFileSystemHandler
{
@@ -83,6 +83,14 @@ namespace WireMock.Handlers
/// <param name="bytes">The bytes.</param>
void WriteFile([NotNull] string filename, [NotNull] byte[] bytes);
/// <summary>
/// Write a file.
/// </summary>
/// <param name="folder">The folder.</param>
/// <param name="filename">The filename.</param>
/// <param name="bytes">The bytes.</param>
void WriteFile([NotNull] string folder, [NotNull] string filename, [NotNull] byte[] bytes);
/// <summary>
/// Read a file as bytes.
/// </summary>

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;
@@ -28,7 +28,7 @@ namespace WireMock
/// <summary>
/// The ProxyUrl (if a proxy is used).
/// </summary>
string ProxyUrl { get; }
string ProxyUrl { get; set; }
/// <summary>
/// Gets the DateTime.
@@ -83,7 +83,7 @@ namespace WireMock
/// <summary>
/// The body.
/// </summary>
IBodyData BodyData { get; }
IBodyData? BodyData { get; }
/// <summary>
/// The original body as string. Convenience getter for Handlebars.

View File

@@ -1,4 +1,4 @@
using System;
using System;
using JetBrains.Annotations;
using WireMock.Admin.Requests;
@@ -17,7 +17,7 @@ namespace WireMock.Logging
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Debug([NotNull] string formatString, [NotNull] params object[] args);
void Debug(string formatString, params object[] args);
/// <summary>
/// Writes the message at the Info level using the specified parameters.
@@ -26,7 +26,7 @@ namespace WireMock.Logging
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Info([NotNull] string formatString, [NotNull] params object[] args);
void Info(string formatString, params object[] args);
/// <summary>
/// Writes the message at the Warning level using the specified parameters.
@@ -35,7 +35,7 @@ namespace WireMock.Logging
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Warn([NotNull] string formatString, [NotNull] params object[] args);
void Warn(string formatString, params object[] args);
/// <summary>
/// Writes the message at the Error level using the specified parameters.
@@ -44,7 +44,7 @@ namespace WireMock.Logging
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Error([NotNull] string formatString, [NotNull] params object[] args);
void Error(string formatString, params object[] args);
/// <summary>
/// Writes the message at the Error level using the specified exception.
@@ -53,7 +53,7 @@ namespace WireMock.Logging
/// <param name="exception">The exception.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Error([NotNull] string formatString, [NotNull] Exception exception);
void Error(string formatString, Exception exception);
/// <summary>
/// Writes the LogEntryModel (LogRequestModel, LogResponseModel and more).
@@ -61,6 +61,6 @@ namespace WireMock.Logging
/// <param name="logEntryModel">The Request Log Model.</param>
/// <param name="isAdminRequest">Defines if this request is an admin request.</param>
[PublicAPI]
void DebugRequestResponse([NotNull] LogEntryModel logEntryModel, bool isAdminRequest);
void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest);
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
namespace WireMock.Matchers.Request
@@ -44,5 +44,13 @@ namespace WireMock.Matchers.Request
/// The match-score.
/// </value>
double TotalScore { get; }
/// <summary>
/// Adds the score.
/// </summary>
/// <param name="matcherType">The matcher Type.</param>
/// <param name="score">The score.</param>
/// <returns>The score.</returns>
double AddScore(Type matcherType, double score);
}
}

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
namespace WireMock.Matchers.Request
{
@@ -15,6 +15,6 @@ namespace WireMock.Matchers.Request
/// <returns>
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
double GetMatchingScore([NotNull] IRequestMessage requestMessage, [NotNull] RequestMatchResult requestMatchResult);
double GetMatchingScore([NotNull] IRequestMessage requestMessage, [NotNull] IRequestMatchResult requestMatchResult);
}
}

View File

@@ -1,61 +1,62 @@
using System.Text;
using System.Diagnostics.CodeAnalysis;
using System.Text;
using JetBrains.Annotations;
using WireMock.Types;
namespace WireMock.Util
namespace WireMock.Util;
/// <summary>
/// IBodyData
/// </summary>
public interface IBodyData
{
/// <summary>
/// IBodyData
/// The body (as bytearray).
/// </summary>
public interface IBodyData
{
/// <summary>
/// The body (as bytearray).
/// </summary>
byte[] BodyAsBytes { get; set; }
byte[] BodyAsBytes { get; set; }
/// <summary>
/// Gets or sets the body as a file.
/// </summary>
string BodyAsFile { get; set; }
/// <summary>
/// Gets or sets the body as a file.
/// </summary>
string BodyAsFile { get; set; }
/// <summary>
/// Is the body as file cached?
/// </summary>
bool? BodyAsFileIsCached { get; set; }
/// <summary>
/// Is the body as file cached?
/// </summary>
bool? BodyAsFileIsCached { get; set; }
/// <summary>
/// The body (as JSON object).
/// </summary>
object BodyAsJson { get; set; }
/// <summary>
/// The body (as JSON object).
/// </summary>
object? BodyAsJson { get; set; }
/// <summary>
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
/// </summary>
bool? BodyAsJsonIndented { get; set; }
/// <summary>
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
/// </summary>
bool? BodyAsJsonIndented { get; set; }
/// <summary>
/// The body as string, this is defined when BodyAsString or BodyAsJson are not null.
/// </summary>
string BodyAsString { get; set; }
/// <summary>
/// The body as string, this is defined when BodyAsString or BodyAsJson are not null.
/// </summary>
string BodyAsString { get; set; }
/// <summary>
/// The detected body type (detection based on body content).
/// </summary>
BodyType DetectedBodyType { get; set; }
/// <summary>
/// The detected body type (detection based on body content).
/// </summary>
BodyType? DetectedBodyType { get; set; }
/// <summary>
/// The detected body type (detection based on Content-Type).
/// </summary>
BodyType DetectedBodyTypeFromContentType { get; set; }
/// <summary>
/// The detected body type (detection based on Content-Type).
/// </summary>
BodyType? DetectedBodyTypeFromContentType { get; set; }
/// <summary>
/// The detected compression.
/// </summary>
string DetectedCompression { get; set; }
/// <summary>
/// The detected compression.
/// </summary>
string? DetectedCompression { get; set; }
/// <summary>
/// The body encoding.
/// </summary>
Encoding Encoding { get; set; }
}
/// <summary>
/// The body encoding.
/// </summary>
Encoding? Encoding { get; set; }
}

View File

@@ -4,6 +4,7 @@ using System.Collections.Specialized;
using JetBrains.Annotations;
using WireMock.Admin.Mappings;
using WireMock.Logging;
using WireMock.Matchers.Request;
namespace WireMock.Server
{
@@ -51,7 +52,17 @@ namespace WireMock.Server
/// <summary>
/// Gets the first url.
/// </summary>
string Url { get; }
string? Url { get; }
/// <summary>
/// Gets the consumer.
/// </summary>
string? Consumer { get; }
/// <summary>
/// Gets the provider.
/// </summary>
string? Provider { get; }
//ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
@@ -94,7 +105,7 @@ namespace WireMock.Server
//IEnumerable<LogEntry> FindLogEntries([NotNull] params IRequestMatcher[] matchers);
//IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);
// IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);
/// <summary>
/// Reads a static mapping file and adds or updates a single mapping.
@@ -102,7 +113,7 @@ namespace WireMock.Server
/// Calling this method manually forces WireMock.Net to read and apply the specified static mapping file.
/// </summary>
/// <param name="path">The path to the static mapping file.</param>
bool ReadStaticMappingAndAddOrUpdate([NotNull] string path);
bool ReadStaticMappingAndAddOrUpdate(string path);
/// <summary>
/// Reads the static mappings from a folder.
@@ -111,7 +122,7 @@ namespace WireMock.Server
/// Calling this method manually forces WireMock.Net to read and apply all static mapping files in the specified folder.
/// </summary>
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
void ReadStaticMappings([CanBeNull] string folder = null);
void ReadStaticMappings(string? folder = null);
/// <summary>
/// Removes the authentication.
@@ -142,33 +153,33 @@ namespace WireMock.Server
/// Saves the static mappings.
/// </summary>
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
void SaveStaticMappings([CanBeNull] string folder = null);
void SaveStaticMappings(string? folder = null);
/// <summary>
/// Sets the basic authentication.
/// </summary>
/// <param name="tenant">The Tenant.</param>
/// <param name="audience">The Audience or Resource.</param>
void SetAzureADAuthentication([NotNull] string tenant, [NotNull] string audience);
void SetAzureADAuthentication(string tenant, string audience);
/// <summary>
/// Sets the basic authentication.
/// </summary>
/// <param name="username">The username.</param>
/// <param name="password">The password.</param>
void SetBasicAuthentication([NotNull] string username, [NotNull] string password);
void SetBasicAuthentication(string username, string password);
/// <summary>
/// Sets the maximum RequestLog count.
/// </summary>
/// <param name="maxRequestLogCount">The maximum RequestLog count.</param>
void SetMaxRequestLogCount([CanBeNull] int? maxRequestLogCount);
void SetMaxRequestLogCount(int? maxRequestLogCount);
/// <summary>
/// Sets RequestLog expiration in hours.
/// </summary>
/// <param name="requestLogExpirationDuration">The RequestLog expiration in hours.</param>
void SetRequestLogExpirationDuration([CanBeNull] int? requestLogExpirationDuration);
void SetRequestLogExpirationDuration(int? requestLogExpirationDuration);
/// <summary>
/// Stop this server.
@@ -179,7 +190,7 @@ namespace WireMock.Server
/// Watches the static mappings for changes.
/// </summary>
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
void WatchStaticMappings([CanBeNull] string folder = null);
void WatchStaticMappings(string? folder = null);
/// <summary>
/// Register the mappings (via <see cref="MappingModel"/>).

View File

@@ -1,36 +1,36 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>An OpenApi (swagger) parser to generate MappingModel or mapping.json file.</Description>
<TargetFrameworks>net46;netstandard2.0;netstandard2.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;openapi;OAS;converter;parser;openapiparser</PackageTags>
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5AADAD}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup>
<Description>An OpenApi (swagger) parser to generate MappingModel or mapping.json file.</Description>
<TargetFrameworks>net46;netstandard2.0;netstandard2.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;openapi;OAS;converter;parser;openapiparser</PackageTags>
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5AADAD}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.2.3" />
<PackageReference Include="RamlToOpenApiConverter" Version="0.6.1" />
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.14" />
<PackageReference Include="Stef.Validation" Version="0.1.0" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.2.3" />
<PackageReference Include="RamlToOpenApiConverter" Version="0.6.1" />
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.14" />
<PackageReference Include="Stef.Validation" Version="0.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
</ItemGroup>
</Project>

View File

@@ -106,7 +106,7 @@ namespace WireMock.Handlers
return File.Exists(AdjustPathForMappingFolder(filename));
}
/// <inheritdoc cref="IFileSystemHandler.WriteFile(string, byte[])"/>
/// <inheritdoc />
public virtual void WriteFile(string filename, byte[] bytes)
{
Guard.NotNullOrEmpty(filename, nameof(filename));
@@ -115,6 +115,16 @@ namespace WireMock.Handlers
File.WriteAllBytes(AdjustPathForMappingFolder(filename), bytes);
}
/// <inheritdoc />
public virtual void WriteFile(string folder, string filename, byte[] bytes)
{
Guard.NotNullOrEmpty(folder);
Guard.NotNullOrEmpty(filename);
Guard.NotNull(bytes);
File.WriteAllBytes(PathUtils.Combine(folder, filename), bytes);
}
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
public virtual void DeleteFile(string filename)
{

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
@@ -12,7 +12,7 @@ namespace WireMock.Http
{
internal static class HttpRequestMessageHelper
{
internal static HttpRequestMessage Create([NotNull] RequestMessage requestMessage, [NotNull] string url)
internal static HttpRequestMessage Create([NotNull] IRequestMessage requestMessage, [NotNull] string url)
{
Guard.NotNull(requestMessage, nameof(requestMessage));
Guard.NotNullOrEmpty(url, nameof(url));

View File

@@ -26,7 +26,7 @@ namespace WireMock.Http
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}
public Task<HttpResponseMessage> SendAsync([NotNull] HttpClient client, [NotNull] IWebhookRequest request, [NotNull] RequestMessage originalRequestMessage, [NotNull] ResponseMessage originalResponseMessage)
public Task<HttpResponseMessage> SendAsync([NotNull] HttpClient client, [NotNull] IWebhookRequest request, [NotNull] IRequestMessage originalRequestMessage, [NotNull] IResponseMessage originalResponseMessage)
{
Guard.NotNull(client, nameof(client));
Guard.NotNull(request, nameof(request));

View File

@@ -28,6 +28,11 @@ namespace WireMock
/// </summary>
string Title { get; }
/// <summary>
/// Gets the description.
/// </summary>
string Description { get; }
/// <summary>
/// The full filename path for this mapping (only defined for static mappings).
/// </summary>
@@ -117,7 +122,7 @@ namespace WireMock
/// </summary>
/// <param name="requestMessage">The request message.</param>
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage);
Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage);
/// <summary>
/// Gets the RequestMatchResult based on the RequestMessage.
@@ -125,6 +130,6 @@ namespace WireMock
/// <param name="requestMessage">The request message.</param>
/// <param name="nextState">The Next State.</param>
/// <returns>The <see cref="IRequestMatchResult"/>.</returns>
RequestMatchResult GetRequestMatchResult(RequestMessage requestMessage, [CanBeNull] string nextState);
IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, [CanBeNull] string nextState);
}
}

View File

@@ -19,6 +19,9 @@ namespace WireMock
/// <inheritdoc />
public string Title { get; }
/// <inheritdoc />
public string Description { get; }
/// <inheritdoc />
public string Path { get; set; }
@@ -69,6 +72,7 @@ namespace WireMock
/// </summary>
/// <param name="guid">The unique identifier.</param>
/// <param name="title">The unique title (can be null).</param>
/// <param name="description">The description (can be null).</param>
/// <param name="path">The full file path from this mapping title (can be null).</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <param name="requestMatcher">The request matcher.</param>
@@ -82,21 +86,23 @@ namespace WireMock
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
public Mapping(
Guid guid,
[CanBeNull] string title,
[CanBeNull] string path,
[NotNull] WireMockServerSettings settings,
[NotNull] IRequestMatcher requestMatcher,
[NotNull] IResponseProvider provider,
string? title,
string? description,
string? path,
WireMockServerSettings settings,
IRequestMatcher requestMatcher,
IResponseProvider provider,
int priority,
[CanBeNull] string scenario,
[CanBeNull] string executionConditionState,
[CanBeNull] string nextState,
[CanBeNull] int? stateTimes,
[CanBeNull] IWebhook[] webhooks,
[CanBeNull] ITimeSettings timeSettings)
string? scenario,
string? executionConditionState,
string? nextState,
int? stateTimes,
IWebhook[]? webhooks,
ITimeSettings? timeSettings)
{
Guid = guid;
Title = title;
Description = description;
Path = path;
Settings = settings;
RequestMatcher = requestMatcher;
@@ -111,13 +117,13 @@ namespace WireMock
}
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
public Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage)
public Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
{
return Provider.ProvideResponseAsync(requestMessage, Settings);
}
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
public RequestMatchResult GetRequestMatchResult(RequestMessage requestMessage, string nextState)
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string nextState)
{
var result = new RequestMatchResult();

View File

@@ -114,8 +114,8 @@ namespace WireMock.Matchers.Request
Matchers = matchers;
}
/// <see cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = CalculateMatchScore(requestMessage);
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
@@ -50,8 +50,8 @@ namespace WireMock.Matchers.Request
Funcs = funcs;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Stef.Validation;
@@ -33,8 +33,8 @@ namespace WireMock.Matchers.Request
RequestMatchers = requestMatchers;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
if (!RequestMatchers.Any())
{

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
@@ -90,8 +90,8 @@ namespace WireMock.Matchers.Request
Funcs = funcs;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -91,8 +91,8 @@ namespace WireMock.Matchers.Request
Funcs = funcs;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Linq;
using JetBrains.Annotations;
using Stef.Validation;
@@ -30,8 +30,8 @@ namespace WireMock.Matchers.Request
Methods = methods;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = MatchBehaviourHelper.Convert(_matchBehaviour, IsMatch(requestMessage));
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -83,8 +83,8 @@ namespace WireMock.Matchers.Request
Funcs = funcs;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = MatchBehaviourHelper.Convert(_matchBehaviour, IsMatch(requestMessage));
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
@@ -53,7 +53,7 @@ namespace WireMock.Matchers.Request
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
namespace WireMock.Matchers.Request
{
@@ -32,7 +32,7 @@ namespace WireMock.Matchers.Request
}
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = IsMatch();
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
@@ -50,8 +50,8 @@ namespace WireMock.Matchers.Request
Funcs = funcs;
}
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(IRequestMessage requestMessage, RequestMatchResult requestMatchResult)
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
return requestMatchResult.AddScore(GetType(), score);

View File

@@ -1,4 +1,4 @@
using System.Text;
using System.Text;
using WireMock.Types;
namespace WireMock.Util
@@ -9,33 +9,33 @@ namespace WireMock.Util
public class BodyData : IBodyData
{
/// <inheritdoc cref="IBodyData.Encoding" />
public Encoding Encoding { get; set; }
public Encoding? Encoding { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsBytes" />
public string BodyAsString { get; set; }
public string? BodyAsString { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsJson" />
public object BodyAsJson { get; set; }
public object? BodyAsJson { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsBytes" />
public byte[] BodyAsBytes { get; set; }
public byte[]? BodyAsBytes { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsJsonIndented" />
public bool? BodyAsJsonIndented { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsFile" />
public string BodyAsFile { get; set; }
public string? BodyAsFile { get; set; }
/// <inheritdoc cref="IBodyData.BodyAsFileIsCached" />
public bool? BodyAsFileIsCached { get; set; }
/// <inheritdoc cref="IBodyData.DetectedBodyType" />
public BodyType DetectedBodyType { get; set; }
public BodyType? DetectedBodyType { get; set; }
/// <inheritdoc cref="IBodyData.DetectedBodyTypeFromContentType" />
public BodyType DetectedBodyTypeFromContentType { get; set; }
public BodyType? DetectedBodyTypeFromContentType { get; set; }
/// <inheritdoc cref="IRequestMessage.DetectedCompression" />
public string DetectedCompression { get; set; }
public string? DetectedCompression { get; set; }
}
}

View File

@@ -4,7 +4,6 @@ using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Util;
using JetBrains.Annotations;
using WireMock.Types;
#if !USE_ASPNETCORE
using Owin;
@@ -21,7 +20,7 @@ namespace WireMock.Owin
TimeSpan? RequestProcessingDelay { get; set; }
IStringMatcher AuthenticationMatcher { get; set; }
IStringMatcher? AuthenticationMatcher { get; set; }
bool? AllowPartialMapping { get; set; }
@@ -35,17 +34,17 @@ namespace WireMock.Owin
int? MaxRequestLogCount { get; set; }
Action<IAppBuilder> PreWireMockMiddlewareInit { get; set; }
Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
Action<IAppBuilder> PostWireMockMiddlewareInit { get; set; }
Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
#if USE_ASPNETCORE
Action<IServiceCollection> AdditionalServiceRegistration { get; set; }
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
CorsPolicyOptions? CorsPolicyOptions { get; set; }
#endif
IFileSystemHandler FileSystemHandler { get; set; }
IFileSystemHandler? FileSystemHandler { get; set; }
bool? AllowBodyForAllHttpMethods { get; set; }
@@ -57,15 +56,15 @@ namespace WireMock.Owin
bool? HandleRequestsSynchronously { get; set; }
string X509StoreName { get; set; }
string? X509StoreName { get; set; }
string X509StoreLocation { get; set; }
string? X509StoreLocation { get; set; }
string X509ThumbprintOrSubjectName { get; set; }
string? X509ThumbprintOrSubjectName { get; set; }
string X509CertificateFilePath { get; set; }
string? X509CertificateFilePath { get; set; }
string X509CertificatePassword { get; set; }
string? X509CertificatePassword { get; set; }
bool CustomCertificateDefined { get; }

View File

@@ -1,4 +1,4 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
#if !USE_ASPNETCORE
using IResponse = Microsoft.Owin.IOwinResponse;
#else
@@ -17,6 +17,6 @@ namespace WireMock.Owin.Mappers
/// </summary>
/// <param name="responseMessage">The ResponseMessage</param>
/// <param name="response">The OwinResponse/HttpResponse</param>
Task MapAsync(ResponseMessage responseMessage, IResponse response);
Task MapAsync(IResponseMessage responseMessage, IResponse response);
}
}

View File

@@ -53,7 +53,7 @@ namespace WireMock.Owin.Mappers
}
/// <inheritdoc cref="IOwinResponseMapper.MapAsync"/>
public async Task MapAsync(ResponseMessage responseMessage, IResponse response)
public async Task MapAsync(IResponseMessage responseMessage, IResponse response)
{
if (responseMessage == null)
{
@@ -117,12 +117,12 @@ namespace WireMock.Owin.Mappers
return code;
}
private bool IsFault(ResponseMessage responseMessage)
private bool IsFault(IResponseMessage responseMessage)
{
return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
}
private byte[] GetNormalBody(ResponseMessage responseMessage)
private byte[] GetNormalBody(IResponseMessage responseMessage)
{
byte[] bytes = null;
switch (responseMessage.BodyData?.DetectedBodyType)
@@ -151,7 +151,7 @@ namespace WireMock.Owin.Mappers
return bytes;
}
private static void SetResponseHeaders(ResponseMessage responseMessage, IResponse response)
private static void SetResponseHeaders(IResponseMessage responseMessage, IResponse response)
{
// Force setting the Date header (#577)
AppendResponseHeader(

View File

@@ -1,4 +1,4 @@
using WireMock.Matchers.Request;
using WireMock.Matchers.Request;
namespace WireMock.Owin
{
@@ -6,6 +6,6 @@ namespace WireMock.Owin
{
public IMapping Mapping { get; set; }
public RequestMatchResult RequestMatchResult { get; set; }
public IRequestMatchResult RequestMatchResult { get; set; }
}
}

View File

@@ -72,7 +72,7 @@ namespace WireMock.Owin
var request = await _requestMapper.MapAsync(ctx.Request, _options).ConfigureAwait(false);
var logRequest = false;
ResponseMessage response = null;
IResponseMessage response = null;
(MappingMatcherResult Match, MappingMatcherResult Partial) result = (null, null);
try
{
@@ -192,7 +192,7 @@ namespace WireMock.Owin
await CompletedTask.ConfigureAwait(false);
}
private async Task SendToWebhooksAsync(IMapping mapping, RequestMessage request, ResponseMessage response)
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
{
for (int index = 0; index < mapping.Webhooks.Length; index++)
{

View File

@@ -0,0 +1,13 @@
namespace WireMock.Pact.Models.V2
{
public class Interaction
{
public string Description { get; set; } = string.Empty;
public string ProviderState { get; set; }
public Request Request { get; set; } = new Request();
public Response Response { get; set; } = new Response();
}
}

View File

@@ -0,0 +1,25 @@
namespace WireMock.Pact.Models.V2
{
public class MatchingRule
{
/// <summary>
/// type or regex
/// </summary>
public string Match { get; set; } = "type";
/// <summary>
/// Used for Match = "type"
/// </summary>
public string Min { get; set; }
/// <summary>
/// Used for Match = "type"
/// </summary>
public string Max { get; set; }
/// <summary>
/// Used for Match = "regex"
/// </summary>
public string Regex { get; set; }
}
}

View File

@@ -0,0 +1,9 @@
namespace WireMock.Pact.Models.V2
{
public class Metadata
{
public string PactSpecificationVersion { get; set; }
public PactSpecification PactSpecification { get; set; } = new PactSpecification();
}
}

View File

@@ -0,0 +1,15 @@
using System.Collections.Generic;
namespace WireMock.Pact.Models.V2
{
public class Pact
{
public Pacticipant Consumer { get; set; }
public List<Interaction> Interactions { get; set; } = new List<Interaction>();
public Metadata Metadata { get; set; }
public Pacticipant Provider { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
namespace WireMock.Pact.Models.V2
{
public class PactRust
{
public string Ffi { get; set; }
public string Mockserver { get; set; }
public string Models { get; set; }
}
}

View File

@@ -0,0 +1,7 @@
namespace WireMock.Pact.Models.V2
{
public class PactSpecification
{
public string Version { get; set; } = "2.0";
}
}

View File

@@ -0,0 +1,7 @@
namespace WireMock.Pact.Models.V2
{
public class Pacticipant
{
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,11 @@
using System.Collections.Generic;
namespace WireMock.Pact.Models.V2
{
public class ProviderState
{
public string Name { get; set; }
public IDictionary<string, string> Params { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
namespace WireMock.Pact.Models.V2;
public class Request
{
public IDictionary<string, string>? Headers { get; set; }
public string Method { get; set; } = "GET";
public string? Path { get; set; } = "/";
public string? Query { get; set; }
public object? Body { get; set; }
}

View File

@@ -0,0 +1,12 @@
using System.Collections.Generic;
namespace WireMock.Pact.Models.V2;
public class Response
{
public object? Body { get; set; }
public IDictionary<string, string>? Headers { get; set; }
public int Status { get; set; } = 200;
}

View File

@@ -0,0 +1,206 @@
{
"$schema": "http://json-schema.org/draft-04/schema",
"definitions": {
"headers": {
"additionalProperties": {
"type": "string"
},
"type": "object"
},
"interaction": {
"additionalProperties": false,
"properties": {
"description": {
"type": "string"
},
"providerState": {
"type": "string"
},
"request": {
"$ref": "#/definitions/request"
},
"response": {
"$ref": "#/definitions/response"
}
},
"required": [
"description",
"request",
"response"
],
"type": "object"
},
"interactions": {
"items": {
"$ref": "#/definitions/interaction"
},
"type": "array"
},
"matchingRules": {
"additionalProperties": false,
"patternProperties": {
"^\\$.*$": {
"oneOf": [
{
"additionalProperties": false,
"properties": {
"match": {
"enum": [ "type" ],
"type": "string"
},
"max": {
"type": "number"
},
"min": {
"type": "number"
}
},
"required": [ "match" ],
"type": "object"
},
{
"additionalProperties": false,
"properties": {
"match": {
"enum": [ "regex" ],
"type": "string"
},
"regex": {
"type": "string"
}
},
"required": [
"match",
"regex"
],
"type": "object"
}
]
}
},
"type": "object"
},
"metadata": {
"properties": {
"pactSpecification": {
"additionalProperties": false,
"properties": {
"version": {
"type": "string"
}
},
"required": [ "version" ],
"type": "object"
},
"pactSpecificationVersion": {
"type": "string"
},
"pact-specification": {
"additionalProperties": false,
"properties": {
"version": {
"type": "string"
}
},
"required": [ "version" ],
"type": "object"
}
},
"type": "object"
},
"pacticipant": {
"properties": {
"name": {
"type": "string"
}
},
"required": [ "name" ],
"type": "object"
},
"request": {
"additionalProperties": false,
"properties": {
"body": {},
"headers": {
"$ref": "#/definitions/headers"
},
"matchingRules": {
"$ref": "#/definitions/matchingRules"
},
"method": {
"enum": [
"connect",
"CONNECT",
"delete",
"DELETE",
"get",
"GET",
"head",
"HEAD",
"options",
"OPTIONS",
"post",
"POST",
"put",
"PUT",
"trace",
"TRACE"
],
"type": "string"
},
"path": {
"type": "string"
},
"query": {
"pattern": "^$|^[^=&]+=[^=&]+&?$|^[^=&]+=[^=&]+(&[^=&]+=[^=&]+)*&?$",
"type": "string"
}
},
"required": [
"method",
"path"
],
"type": "object"
},
"response": {
"additionalProperties": false,
"properties": {
"body": {},
"headers": {
"$ref": "#/definitions/headers"
},
"matchingRules": {
"$ref": "#/definitions/matchingRules"
},
"status": {
"maximum": 599,
"minimum": 100,
"type": "integer"
}
},
"required": [ "status" ],
"type": "object"
}
},
"description": "Schema for a Pact file",
"properties": {
"consumer": {
"$ref": "#/definitions/pacticipant"
},
"interactions": {
"$ref": "#/definitions/interactions"
},
"metadata": {
"$ref": "#/definitions/metadata"
},
"provider": {
"$ref": "#/definitions/pacticipant"
}
},
"required": [
"consumer",
"interactions",
"provider"
],
"type": "object"
}

View File

@@ -1,8 +1,8 @@
using System.Runtime.CompilerServices;
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("WireMock.Net.Matchers.CSharpCode, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
[assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
// Needed for Moq in the UnitTest project
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

View File

@@ -24,10 +24,10 @@ namespace WireMock.Proxy
_settings = Guard.NotNull(settings, nameof(settings));
}
public async Task<(ResponseMessage Message, IMapping Mapping)> SendAsync(
public async Task<(IResponseMessage Message, IMapping Mapping)> SendAsync(
[NotNull] ProxyAndRecordSettings proxyAndRecordSettings,
[NotNull] HttpClient client,
[NotNull] RequestMessage requestMessage,
[NotNull] IRequestMessage requestMessage,
[NotNull] string url)
{
Guard.NotNull(client, nameof(client));
@@ -59,7 +59,7 @@ namespace WireMock.Proxy
return (responseMessage, mapping);
}
private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, RequestMessage requestMessage, ResponseMessage responseMessage)
private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, IRequestMessage requestMessage, ResponseMessage responseMessage)
{
string[] excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { };
string[] excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };
@@ -104,7 +104,7 @@ namespace WireMock.Proxy
var response = Response.Create(responseMessage);
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null, null, null);
return new Mapping(Guid.NewGuid(), string.Empty, string.Empty, null, _settings, request, response, 0, null, null, null, null, null, null);
}
}
}

View File

@@ -1,4 +1,3 @@
using JetBrains.Annotations;
using System;
using System.Text;
using System.Threading.Tasks;
@@ -17,7 +16,7 @@ namespace WireMock.ResponseBuilders
/// <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([NotNull] string body, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
IResponseBuilder WithBody(string body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
/// <summary>
/// WithBody : Create a ... response based on a callback function.
@@ -26,7 +25,7 @@ namespace WireMock.ResponseBuilders
/// <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([NotNull] Func<RequestMessage, string> bodyFactory, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
/// <summary>
/// WithBody : Create a ... response based on a callback function.
@@ -35,7 +34,7 @@ namespace WireMock.ResponseBuilders
/// <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([NotNull] Func<RequestMessage, Task<string>> bodyFactory, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null);
/// <summary>
/// WithBody : Create a ... response based on a bytearray.
@@ -44,7 +43,7 @@ namespace WireMock.ResponseBuilders
/// <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([NotNull] byte[] body, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
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).
@@ -53,7 +52,7 @@ namespace WireMock.ResponseBuilders
/// <param name="encoding">The body encoding.</param>
/// <param name="indented">Use JSON indented.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithBodyAsJson([NotNull] object body, [CanBeNull] Encoding encoding = null, bool? indented = null);
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).
@@ -61,7 +60,7 @@ namespace WireMock.ResponseBuilders
/// <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([NotNull] object body, bool indented);
IResponseBuilder WithBodyAsJson(object body, bool indented);
/// <summary>
/// WithBodyFromFile : Create a ... response based on a File.
@@ -69,6 +68,6 @@ namespace WireMock.ResponseBuilders
/// <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([NotNull] string filename, bool cache = true);
IResponseBuilder WithBodyFromFile(string filename, bool cache = true);
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.ResponseProviders;
@@ -15,13 +15,13 @@ namespace WireMock.ResponseBuilders
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
IResponseBuilder WithCallback([NotNull] Func<IRequestMessage, ResponseMessage> callbackHandler);
/// <summary>
/// The async callback builder
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, Task<ResponseMessage>> callbackHandler);
IResponseBuilder WithCallback([NotNull] Func<IRequestMessage, Task<ResponseMessage>> callbackHandler);
}
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using Stef.Validation;
@@ -9,35 +9,35 @@ namespace WireMock.ResponseBuilders
/// <summary>
/// A delegate to execute to generate the response.
/// </summary>
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }
public Func<IRequestMessage, ResponseMessage> Callback { get; private set; }
/// <summary>
/// A delegate to execute to generate the response async.
/// </summary>
public Func<RequestMessage, Task<ResponseMessage>> CallbackAsync { get; private set; }
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 cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, ResponseMessage})"/>
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
/// <inheritdoc />
public IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler)
{
Guard.NotNull(callbackHandler, nameof(callbackHandler));
return WithCallbackInternal(true, callbackHandler);
}
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, Task{ResponseMessage}})"/>
public IResponseBuilder WithCallback(Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
/// <inheritdoc />
public IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
{
Guard.NotNull(callbackHandler, nameof(callbackHandler));
return WithCallbackInternal(true, callbackHandler);
}
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, ResponseMessage> callbackHandler)
{
Guard.NotNull(callbackHandler, nameof(callbackHandler));
@@ -47,7 +47,7 @@ namespace WireMock.ResponseBuilders
return this;
}
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
{
Guard.NotNull(callbackHandler, nameof(callbackHandler));

View File

@@ -195,8 +195,8 @@ namespace WireMock.ResponseBuilders
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(Func{RequestMessage, string}, string, Encoding)"/>
public IResponseBuilder WithBody(Func<RequestMessage, string> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
/// <inheritdoc />
public IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Guard.NotNull(bodyFactory, nameof(bodyFactory));
@@ -211,8 +211,8 @@ namespace WireMock.ResponseBuilders
});
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(Func{RequestMessage, Task{string}}, string, Encoding)"/>
public IResponseBuilder WithBody(Func<RequestMessage, Task<string>> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
/// <inheritdoc />
public IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Guard.NotNull(bodyFactory, nameof(bodyFactory));
@@ -383,8 +383,8 @@ namespace WireMock.ResponseBuilders
return this;
}
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, WireMockServerSettings)"/>
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
/// <inheritdoc />
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{
Guard.NotNull(requestMessage, nameof(requestMessage));
Guard.NotNull(settings, nameof(settings));

View File

@@ -6,14 +6,14 @@ namespace WireMock.ResponseProviders
{
internal class DynamicAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, Task<ResponseMessage>> _responseMessageFunc;
private readonly Func<IRequestMessage, Task<IResponseMessage>> _responseMessageFunc;
public DynamicAsyncResponseProvider(Func<RequestMessage, Task<ResponseMessage>> responseMessageFunc)
public DynamicAsyncResponseProvider(Func<IRequestMessage, Task<IResponseMessage>> responseMessageFunc)
{
_responseMessageFunc = responseMessageFunc;
}
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{
return (await _responseMessageFunc(requestMessage).ConfigureAwait(false), null);
}

View File

@@ -6,16 +6,16 @@ namespace WireMock.ResponseProviders
{
internal class DynamicResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, ResponseMessage> _responseMessageFunc;
private readonly Func<IRequestMessage, IResponseMessage> _responseMessageFunc;
public DynamicResponseProvider(Func<RequestMessage, ResponseMessage> responseMessageFunc)
public DynamicResponseProvider(Func<IRequestMessage, IResponseMessage> responseMessageFunc)
{
_responseMessageFunc = responseMessageFunc;
}
public Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
public Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{
(ResponseMessage responseMessage, IMapping mapping) result = (_responseMessageFunc(requestMessage), null);
(IResponseMessage responseMessage, IMapping mapping) result = (_responseMessageFunc(requestMessage), null);
return Task.FromResult(result);
}
}

View File

@@ -1,4 +1,4 @@
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -17,6 +17,6 @@ namespace WireMock.ResponseProviders
/// <param name="requestMessage">The request.</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync([NotNull] RequestMessage requestMessage, [NotNull] WireMockServerSettings settings);
Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync([NotNull] IRequestMessage requestMessage, [NotNull] WireMockServerSettings settings);
}
}

View File

@@ -6,16 +6,16 @@ namespace WireMock.ResponseProviders
{
internal class ProxyAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, WireMockServerSettings, Task<ResponseMessage>> _responseMessageFunc;
private readonly Func<IRequestMessage, WireMockServerSettings, Task<IResponseMessage>> _responseMessageFunc;
private readonly WireMockServerSettings _settings;
public ProxyAsyncResponseProvider(Func<RequestMessage, WireMockServerSettings, Task<ResponseMessage>> responseMessageFunc, WireMockServerSettings settings)
public ProxyAsyncResponseProvider(Func<IRequestMessage, WireMockServerSettings, Task<IResponseMessage>> responseMessageFunc, WireMockServerSettings settings)
{
_responseMessageFunc = responseMessageFunc;
_settings = settings;
}
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{
return (await _responseMessageFunc(requestMessage, _settings).ConfigureAwait(false), null);
}

View File

@@ -20,5 +20,11 @@ namespace WireMock.Serialization
{
DateParseHandling = DateParseHandling.None
};
public static readonly JsonSerializerSettings JsonSerializerSettingsPact = new JsonSerializerSettings
{
Formatting = Formatting.Indented,
NullValueHandling = NullValueHandling.Ignore
};
}
}

View File

@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using WireMock.Admin.Mappings;
using WireMock.Admin.Requests;
using WireMock.Logging;
@@ -29,8 +29,8 @@ namespace WireMock.Serialization
if (logEntry.RequestMessage.BodyData != null)
{
logRequestModel.DetectedBodyType = logEntry.RequestMessage.BodyData.DetectedBodyType.ToString();
logRequestModel.DetectedBodyTypeFromContentType = logEntry.RequestMessage.BodyData.DetectedBodyTypeFromContentType.ToString();
logRequestModel.DetectedBodyType = logEntry.RequestMessage.BodyData.DetectedBodyType?.ToString();
logRequestModel.DetectedBodyTypeFromContentType = logEntry.RequestMessage.BodyData.DetectedBodyTypeFromContentType?.ToString();
switch (logEntry.RequestMessage.BodyData.DetectedBodyType)
{

View File

@@ -40,6 +40,7 @@ namespace WireMock.Serialization
Guid = mapping.Guid,
TimeSettings = TimeSettingsMapper.Map(mapping.TimeSettings),
Title = mapping.Title,
Description = mapping.Description,
Priority = mapping.Priority != 0 ? mapping.Priority : (int?)null,
Scenario = mapping.Scenario,
WhenStateIs = mapping.ExecutionConditionState,

View File

@@ -1,51 +1,49 @@
using System.IO;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Settings;
using Stef.Validation;
using WireMock.Settings;
namespace WireMock.Serialization
namespace WireMock.Serialization;
internal class MappingToFileSaver
{
internal class MappingToFileSaver
private readonly WireMockServerSettings _settings;
private readonly MappingConverter _mappingConverter;
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
{
private readonly WireMockServerSettings _settings;
private readonly MappingConverter _mappingConverter;
Guard.NotNull(settings);
Guard.NotNull(mappingConverter);
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
_settings = settings;
_mappingConverter = mappingConverter;
}
public void SaveMappingToFile(IMapping mapping, string? folder = null)
{
if (folder == null)
{
Guard.NotNull(settings);
Guard.NotNull(mappingConverter);
_settings = settings;
_mappingConverter = mappingConverter;
folder = _settings.FileSystemHandler.GetMappingFolder();
}
public void SaveMappingToFile(IMapping mapping, [CanBeNull] string folder = null)
if (!_settings.FileSystemHandler.FolderExists(folder))
{
if (folder == null)
{
folder = _settings.FileSystemHandler.GetMappingFolder();
}
if (!_settings.FileSystemHandler.FolderExists(folder))
{
_settings.FileSystemHandler.CreateFolder(folder);
}
var model = _mappingConverter.ToMappingModel(mapping);
string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString()) + ".json";
string path = Path.Combine(folder, filename);
_settings.Logger.Info("Saving Mapping file {0}", filename);
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault));
_settings.FileSystemHandler.CreateFolder(folder);
}
private static string SanitizeFileName(string name, char replaceChar = '_')
{
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
}
var model = _mappingConverter.ToMappingModel(mapping);
string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString()) + ".json";
string path = Path.Combine(folder, filename);
_settings.Logger.Info("Saving Mapping file {0}", filename);
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault));
}
private static string SanitizeFileName(string name, char replaceChar = '_')
{
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
}
}

View File

@@ -38,6 +38,13 @@ namespace WireMock.Server
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithTitle(string title);
/// <summary>
/// Define a description for this mapping.
/// </summary>
/// <param name="description">The description.</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider WithDescription(string description);
/// <summary>
/// Define the full filepath for this mapping.
/// </summary>

View File

@@ -21,6 +21,7 @@ namespace WireMock.Server
{
private int _priority;
private string _title;
private string _description;
private string _path;
private string _executionConditionState;
private string _nextState;
@@ -58,16 +59,16 @@ namespace WireMock.Server
/// <param name="provider">The provider.</param>
public void RespondWith(IResponseProvider provider)
{
_registrationCallback(new Mapping(Guid, _title, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhooks, TimeSettings), _saveToFile);
_registrationCallback(new Mapping(Guid, _title, _description, _path, _settings, _requestMatcher, provider, _priority, _scenario, _executionConditionState, _nextState, _timesInSameState, Webhooks, TimeSettings), _saveToFile);
}
/// <see cref="IRespondWithAProvider.WithGuid(string)"/>
/// <inheritdoc />
public IRespondWithAProvider WithGuid(string guid)
{
return WithGuid(Guid.Parse(guid));
}
/// <see cref="IRespondWithAProvider.WithGuid(Guid)"/>
/// <inheritdoc />
public IRespondWithAProvider WithGuid(Guid guid)
{
Guid = guid;
@@ -75,7 +76,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.WithTitle"/>
/// <inheritdoc />
public IRespondWithAProvider WithTitle(string title)
{
_title = title;
@@ -83,6 +84,14 @@ namespace WireMock.Server
return this;
}
/// <inheritdoc />
public IRespondWithAProvider WithDescription(string description)
{
_description = description;
return this;
}
/// <see cref="IRespondWithAProvider.WithPath"/>
public IRespondWithAProvider WithPath(string path)
{
@@ -91,7 +100,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.AtPriority"/>
/// <inheritdoc />
public IRespondWithAProvider AtPriority(int priority)
{
_priority = priority;
@@ -99,7 +108,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.InScenario(string)"/>
/// <inheritdoc />
public IRespondWithAProvider InScenario(string scenario)
{
_scenario = scenario;
@@ -107,13 +116,13 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.InScenario(int)"/>
/// <inheritdoc />
public IRespondWithAProvider InScenario(int scenario)
{
return InScenario(scenario.ToString());
}
/// <see cref="IRespondWithAProvider.WhenStateIs(string)"/>
/// <inheritdoc />
public IRespondWithAProvider WhenStateIs(string state)
{
if (string.IsNullOrEmpty(_scenario))
@@ -126,13 +135,13 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.WhenStateIs(int)"/>
/// <inheritdoc />
public IRespondWithAProvider WhenStateIs(int state)
{
return WhenStateIs(state.ToString());
}
/// <see cref="IRespondWithAProvider.WillSetStateTo(string, int?)"/>
/// <inheritdoc />
public IRespondWithAProvider WillSetStateTo(string state, int? times = 1)
{
if (string.IsNullOrEmpty(_scenario))
@@ -146,7 +155,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.WillSetStateTo(int, int?)"/>
/// <inheritdoc />
public IRespondWithAProvider WillSetStateTo(int state, int? times = 1)
{
return WillSetStateTo(state.ToString(), times);
@@ -162,7 +171,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.WithWebhook(IWebhook[])"/>
/// <inheritdoc />
public IRespondWithAProvider WithWebhook(params IWebhook[] webhooks)
{
Guard.HasNoNulls(webhooks, nameof(webhooks));
@@ -172,7 +181,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.WithWebhook(string, string, IDictionary{string, WireMockList{string}}, string, bool, TransformerType)"/>
/// <inheritdoc />
public IRespondWithAProvider WithWebhook(
[NotNull] string url,
[CanBeNull] string method = "post",
@@ -196,7 +205,7 @@ namespace WireMock.Server
return this;
}
/// <see cref="IRespondWithAProvider.WithWebhook(string, string, IDictionary{string, WireMockList{string}}, object, bool, TransformerType)"/>
/// <inheritdoc />
public IRespondWithAProvider WithWebhook(
[NotNull] string url,
[CanBeNull] string method = "post",

View File

@@ -44,12 +44,12 @@ public partial class WireMockServer
private const string AdminScenarios = "/__admin/scenarios";
private const string QueryParamReloadStaticMappings = "reloadStaticMappings";
private readonly Guid _proxyMappingGuid = new Guid("e59914fd-782e-428e-91c1-4810ffb86567");
private readonly Guid _proxyMappingGuid = new("e59914fd-782e-428e-91c1-4810ffb86567");
private readonly RegexMatcher _adminRequestContentTypeJson = new ContentTypeMatcher(ContentTypeJson, true);
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private readonly RegexMatcher _adminRequestsGuidPathMatcher = new(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
private EnhancedFileSystemWatcher _enhancedFileSystemWatcher;
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
#region InitAdmin
private void InitAdmin()
@@ -108,7 +108,7 @@ public partial class WireMockServer
#region StaticMappings
/// <inheritdoc cref="IWireMockServer.SaveStaticMappings" />
[PublicAPI]
public void SaveStaticMappings([CanBeNull] string folder = null)
public void SaveStaticMappings(string? folder = null)
{
foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
{
@@ -118,7 +118,7 @@ public partial class WireMockServer
/// <inheritdoc cref="IWireMockServer.ReadStaticMappings" />
[PublicAPI]
public void ReadStaticMappings([CanBeNull] string folder = null)
public void ReadStaticMappings(string? folder = null)
{
if (folder == null)
{
@@ -207,8 +207,7 @@ public partial class WireMockServer
#endregion
#region Proxy and Record
[CanBeNull]
private HttpClient _httpClientForProxy;
private HttpClient? _httpClientForProxy;
private void InitProxyAndRecord(WireMockServerSettings settings)
{
@@ -230,7 +229,7 @@ public partial class WireMockServer
proxyRespondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
}
private async Task<ResponseMessage> ProxyAndRecordAsync(RequestMessage requestMessage, WireMockServerSettings settings)
private async Task<IResponseMessage> ProxyAndRecordAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{
var requestUri = new Uri(requestMessage.Url);
var proxyUri = new Uri(settings.ProxyAndRecordSettings.Url);
@@ -263,7 +262,7 @@ public partial class WireMockServer
#endregion
#region Settings
private ResponseMessage SettingsGet(RequestMessage requestMessage)
private IResponseMessage SettingsGet(IRequestMessage requestMessage)
{
var model = new SettingsModel
{
@@ -290,7 +289,7 @@ public partial class WireMockServer
return ToJson(model);
}
private ResponseMessage SettingsUpdate(RequestMessage requestMessage)
private IResponseMessage SettingsUpdate(IRequestMessage requestMessage)
{
var settings = DeserializeObject<SettingsModel>(requestMessage);
@@ -335,7 +334,7 @@ public partial class WireMockServer
#endregion Settings
#region Mapping/{guid}
private ResponseMessage MappingGet(RequestMessage requestMessage)
private IResponseMessage MappingGet(IRequestMessage requestMessage)
{
Guid guid = ParseGuidFromRequestMessage(requestMessage);
var mapping = Mappings.FirstOrDefault(m => !m.IsAdminInterface && m.Guid == guid);
@@ -351,7 +350,7 @@ public partial class WireMockServer
return ToJson(model);
}
private ResponseMessage MappingPut(RequestMessage requestMessage)
private IResponseMessage MappingPut(IRequestMessage requestMessage)
{
Guid guid = ParseGuidFromRequestMessage(requestMessage);
@@ -361,7 +360,7 @@ public partial class WireMockServer
return ResponseMessageBuilder.Create("Mapping added or updated", 200, guidFromPut);
}
private ResponseMessage MappingDelete(RequestMessage requestMessage)
private IResponseMessage MappingDelete(IRequestMessage requestMessage)
{
Guid guid = ParseGuidFromRequestMessage(requestMessage);
@@ -373,14 +372,14 @@ public partial class WireMockServer
return ResponseMessageBuilder.Create("Mapping not found", 404);
}
private Guid ParseGuidFromRequestMessage(RequestMessage requestMessage)
private Guid ParseGuidFromRequestMessage(IRequestMessage requestMessage)
{
return Guid.Parse(requestMessage.Path.Substring(AdminMappings.Length + 1));
}
#endregion Mapping/{guid}
#region Mappings
private ResponseMessage MappingsSave(RequestMessage requestMessage)
private IResponseMessage MappingsSave(IRequestMessage requestMessage)
{
SaveStaticMappings();
@@ -392,12 +391,12 @@ public partial class WireMockServer
return Mappings.Where(m => !m.IsAdminInterface).Select(_mappingConverter.ToMappingModel);
}
private ResponseMessage MappingsGet(RequestMessage requestMessage)
private IResponseMessage MappingsGet(IRequestMessage requestMessage)
{
return ToJson(ToMappingModels());
}
private ResponseMessage MappingsPost(RequestMessage requestMessage)
private IResponseMessage MappingsPost(IRequestMessage requestMessage)
{
try
{
@@ -427,7 +426,7 @@ public partial class WireMockServer
}
}
private Guid? ConvertMappingAndRegisterAsRespondProvider(MappingModel mappingModel, Guid? guid = null, string path = null)
private Guid? ConvertMappingAndRegisterAsRespondProvider(MappingModel mappingModel, Guid? guid = null, string? path = null)
{
Guard.NotNull(mappingModel, nameof(mappingModel));
Guard.NotNull(mappingModel.Request, nameof(mappingModel.Request));
@@ -494,7 +493,7 @@ public partial class WireMockServer
return respondProvider.Guid;
}
private ResponseMessage MappingsDelete(RequestMessage requestMessage)
private IResponseMessage MappingsDelete(IRequestMessage requestMessage)
{
if (!string.IsNullOrEmpty(requestMessage.Body))
{
@@ -519,7 +518,7 @@ public partial class WireMockServer
}
}
private IEnumerable<Guid> MappingsDeleteMappingFromBody(RequestMessage requestMessage)
private IEnumerable<Guid> MappingsDeleteMappingFromBody(IRequestMessage requestMessage)
{
var deletedGuids = new List<Guid>();
@@ -555,7 +554,7 @@ public partial class WireMockServer
return deletedGuids;
}
private ResponseMessage MappingsReset(RequestMessage requestMessage)
private IResponseMessage MappingsReset(IRequestMessage requestMessage)
{
ResetMappings();
@@ -575,7 +574,7 @@ public partial class WireMockServer
#endregion Mappings
#region Request/{guid}
private ResponseMessage RequestGet(RequestMessage requestMessage)
private IResponseMessage RequestGet(IRequestMessage requestMessage)
{
Guid guid = ParseGuidFromRequestMessage(requestMessage);
var entry = LogEntries.FirstOrDefault(r => !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid);
@@ -591,7 +590,7 @@ public partial class WireMockServer
return ToJson(model);
}
private ResponseMessage RequestDelete(RequestMessage requestMessage)
private IResponseMessage RequestDelete(IRequestMessage requestMessage)
{
Guid guid = ParseGuidFromRequestMessage(requestMessage);
@@ -605,7 +604,7 @@ public partial class WireMockServer
#endregion Request/{guid}
#region Requests
private ResponseMessage RequestsGet(RequestMessage requestMessage)
private IResponseMessage RequestsGet(IRequestMessage requestMessage)
{
var result = LogEntries
.Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
@@ -614,7 +613,7 @@ public partial class WireMockServer
return ToJson(result);
}
private ResponseMessage RequestsDelete(RequestMessage requestMessage)
private IResponseMessage RequestsDelete(IRequestMessage requestMessage)
{
ResetLogEntries();
@@ -623,7 +622,7 @@ public partial class WireMockServer
#endregion Requests
#region Requests/find
private ResponseMessage RequestsFind(RequestMessage requestMessage)
private IResponseMessage RequestsFind(IRequestMessage requestMessage)
{
var requestModel = DeserializeObject<RequestModel>(requestMessage);
@@ -646,7 +645,7 @@ public partial class WireMockServer
#endregion Requests/find
#region Scenarios
private ResponseMessage ScenariosGet(RequestMessage requestMessage)
private IResponseMessage ScenariosGet(IRequestMessage requestMessage)
{
var scenariosStates = Scenarios.Values.Select(s => new ScenarioStateModel
{
@@ -660,7 +659,7 @@ public partial class WireMockServer
return ToJson(scenariosStates, true);
}
private ResponseMessage ScenariosReset(RequestMessage requestMessage)
private IResponseMessage ScenariosReset(IRequestMessage requestMessage)
{
ResetScenarios();
@@ -668,7 +667,29 @@ public partial class WireMockServer
}
#endregion
private IRequestBuilder InitRequestBuilder(RequestModel requestModel, bool pathOrUrlRequired)
/// <summary>
/// This stores details about the consumer of the interaction.
/// </summary>
/// <param name="consumer">the consumer</param>
[PublicAPI]
public WireMockServer WithConsumer(string consumer)
{
Consumer = consumer;
return this;
}
/// <summary>
/// This stores details about the provider of the interaction.
/// </summary>
/// <param name="provider">the provider</param>
[PublicAPI]
public WireMockServer WithProvider(string provider)
{
Provider = provider;
return this;
}
private IRequestBuilder? InitRequestBuilder(RequestModel requestModel, bool pathOrUrlRequired)
{
IRequestBuilder requestBuilder = Request.Create();
@@ -743,7 +764,7 @@ public partial class WireMockServer
headerModel.Name,
headerModel.IgnoreCase == true,
headerModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch,
headerModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray()
headerModel.Matchers!.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray()
);
}
}
@@ -756,16 +777,16 @@ public partial class WireMockServer
cookieModel.Name,
cookieModel.IgnoreCase == true,
cookieModel.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch,
cookieModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
cookieModel.Matchers!.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
}
}
if (requestModel.Params != null)
{
foreach (var paramModel in requestModel.Params.Where(p => p != null && p.Matchers != null))
foreach (var paramModel in requestModel.Params.Where(p => p is { Matchers: { } }))
{
bool ignoreCase = paramModel.IgnoreCase == true;
requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers!.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
}
}
@@ -897,12 +918,12 @@ public partial class WireMockServer
};
}
private Encoding ToEncoding(EncodingModel encodingModel)
private Encoding? ToEncoding(EncodingModel? encodingModel)
{
return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
}
private T DeserializeObject<T>(RequestMessage requestMessage)
private T? DeserializeObject<T>(IRequestMessage requestMessage)
{
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.String)
{
@@ -917,9 +938,9 @@ public partial class WireMockServer
return default(T);
}
private T[] DeserializeRequestMessageToArray<T>(RequestMessage requestMessage)
private T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
{
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json)
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json)
{
var bodyAsJson = requestMessage.BodyData.BodyAsJson;

View File

@@ -13,7 +13,7 @@ namespace WireMock.Server
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
#region Files/{filename}
private ResponseMessage FilePost(RequestMessage requestMessage)
private IResponseMessage FilePost(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
@@ -28,7 +28,7 @@ namespace WireMock.Server
return ResponseMessageBuilder.Create("File created");
}
private ResponseMessage FilePut(RequestMessage requestMessage)
private IResponseMessage FilePut(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
@@ -43,7 +43,7 @@ namespace WireMock.Server
return ResponseMessageBuilder.Create("File updated");
}
private ResponseMessage FileGet(RequestMessage requestMessage)
private IResponseMessage FileGet(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
@@ -79,7 +79,7 @@ namespace WireMock.Server
/// Note: Response is returned with no body as a head request doesn't accept a body, only the status code.
/// </summary>
/// <param name="requestMessage">The request message.</param>
private ResponseMessage FileHead(RequestMessage requestMessage)
private IResponseMessage FileHead(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
@@ -92,7 +92,7 @@ namespace WireMock.Server
return ResponseMessageBuilder.Create(204);
}
private ResponseMessage FileDelete(RequestMessage requestMessage)
private IResponseMessage FileDelete(IRequestMessage requestMessage)
{
string filename = GetFileNameFromRequestMessage(requestMessage);
@@ -106,7 +106,7 @@ namespace WireMock.Server
return ResponseMessageBuilder.Create("File deleted.");
}
private string GetFileNameFromRequestMessage(RequestMessage requestMessage)
private string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
{
return Path.GetFileName(requestMessage.Path.Substring(AdminFiles.Length + 1));
}

View File

@@ -21,7 +21,7 @@ namespace WireMock.Server
/// </summary>
/// <param name="path">The path to the WireMock.org mapping json file.</param>
[PublicAPI]
public void ReadStaticWireMockOrgMappingAndAddOrUpdate([NotNull] string path)
public void ReadStaticWireMockOrgMappingAndAddOrUpdate(string path)
{
Guard.NotNull(path, nameof(path));
@@ -44,7 +44,7 @@ namespace WireMock.Server
}
}
private ResponseMessage MappingsPostWireMockOrg(RequestMessage requestMessage)
private IResponseMessage MappingsPostWireMockOrg(IRequestMessage requestMessage)
{
try
{

View File

@@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using WireMock.Admin.Mappings;
using WireMock.Pact.Models.V2;
using WireMock.Util;
namespace WireMock.Server;
public partial class WireMockServer
{
private const string DefaultPath = "/";
private const string DefaultMethod = "GET";
private const int DefaultStatus = 200;
private const string DefaultConsumer = "Default Consumer";
private const string DefaultProvider = "Default Provider";
/// <summary>
/// Save the mappings as a Pact Json file V2.
/// </summary>
/// <param name="folder">The folder to save the pact file.</param>
/// <param name="filename">The filename for the .json file [optional].</param>
public void SavePact(string folder, string? filename = null)
{
var consumer = Consumer ?? DefaultConsumer;
var provider = Provider ?? DefaultProvider;
filename ??= $"{consumer} - {provider}.json";
var pact = new Pact.Models.V2.Pact
{
Consumer = new Pacticipant { Name = consumer },
Provider = new Pacticipant { Name = provider }
};
foreach (var mapping in MappingModels)
{
var interaction = new Interaction
{
Description = mapping.Description,
ProviderState = mapping.Title,
Request = MapRequest(mapping.Request),
Response = MapResponse(mapping.Response)
};
pact.Interactions.Add(interaction);
}
var bytes = JsonUtils.SerializeAsPactFile(pact);
_settings.FileSystemHandler.WriteFile(folder, filename, bytes);
}
private static Request MapRequest(RequestModel request)
{
string path;
switch (request.Path)
{
case string pathAsString:
path = pathAsString;
break;
case PathModel pathModel:
path = GetPatternAsStringFromMatchers(pathModel.Matchers, DefaultPath);
break;
default:
path = DefaultPath;
break;
}
return new Request
{
Method = request.Methods?.FirstOrDefault() ?? DefaultMethod,
Path = path,
Query = MapQueryParameters(request.Params),
Headers = MapRequestHeaders(request.Headers),
Body = MapBody(request.Body)
};
}
private static Response MapResponse(ResponseModel? response)
{
if (response == null)
{
return new Response();
}
return new Response
{
Status = MapStatusCode(response.StatusCode),
Headers = MapResponseHeaders(response.Headers),
Body = response.BodyAsJson
};
}
private static int MapStatusCode(object? statusCode)
{
if (statusCode is string statusCodeAsString)
{
return int.TryParse(statusCodeAsString, out var statusCodeAsInt) ? statusCodeAsInt : DefaultStatus;
}
if (statusCode != null)
{
// Convert to Int32 because Newtonsoft deserializes an 'object' with a number value to a long.
return Convert.ToInt32(statusCode);
}
return DefaultStatus;
}
private static string? MapQueryParameters(IList<ParamModel>? queryParameters)
{
if (queryParameters == null)
{
return null;
}
var values = queryParameters
.Where(qp => qp.Matchers != null && qp.Matchers.Any() && qp.Matchers[0].Pattern is string)
.Select(param => $"{Uri.EscapeDataString(param.Name)}={Uri.EscapeDataString((string)param.Matchers![0].Pattern)}");
return string.Join("&", values);
}
private static IDictionary<string, string>? MapRequestHeaders(IList<HeaderModel>? headers)
{
if (headers == null)
{
return null;
}
var validHeaders = headers.Where(h => h.Matchers != null && h.Matchers.Any() && h.Matchers[0].Pattern is string);
return validHeaders.ToDictionary(x => x.Name, y => (string)y.Matchers![0].Pattern);
}
private static IDictionary<string, string>? MapResponseHeaders(IDictionary<string, object>? headers)
{
if (headers == null)
{
return null;
}
var validHeaders = headers.Where(h => h.Value is string);
return validHeaders.ToDictionary(x => x.Key, y => (string)y.Value);
}
private static object? MapBody(BodyModel? body)
{
if (body == null || body.Matcher.Name != "JsonMatcher")
{
return null;
}
return body.Matcher.Pattern;
}
private static string GetPatternAsStringFromMatchers(MatcherModel[]? matchers, string defaultValue)
{
if (matchers != null && matchers.Any() && matchers[0].Pattern is string patternAsString)
{
return patternAsString;
}
return defaultValue;
}
}

View File

@@ -30,7 +30,7 @@ public partial class WireMockServer : IWireMockServer
private const int ServerStartDelayInMs = 100;
private readonly WireMockServerSettings _settings;
private readonly IOwinSelfHost _httpServer;
private readonly IOwinSelfHost? _httpServer;
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
private readonly MappingConverter _mappingConverter;
private readonly MatcherMapper _matcherMapper;
@@ -38,7 +38,7 @@ public partial class WireMockServer : IWireMockServer
/// <inheritdoc cref="IWireMockServer.IsStarted" />
[PublicAPI]
public bool IsStarted => _httpServer != null && _httpServer.IsStarted;
public bool IsStarted => _httpServer is { IsStarted: true };
/// <inheritdoc />
[PublicAPI]
@@ -54,7 +54,15 @@ public partial class WireMockServer : IWireMockServer
/// <inheritdoc />
[PublicAPI]
public string Url => Urls?.FirstOrDefault();
public string? Url => Urls?.FirstOrDefault();
/// <inheritdoc />
[PublicAPI]
public string? Consumer { get; private set; }
/// <inheritdoc />
[PublicAPI]
public string? Provider { get; private set; }
/// <summary>
/// Gets the mappings.
@@ -100,9 +108,9 @@ public partial class WireMockServer : IWireMockServer
/// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start([NotNull] WireMockServerSettings settings)
public static WireMockServer Start(WireMockServerSettings settings)
{
Guard.NotNull(settings, nameof(settings));
Guard.NotNull(settings);
return new WireMockServer(settings);
}
@@ -114,7 +122,7 @@ public partial class WireMockServer : IWireMockServer
/// <param name="ssl">The SSL support.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start([CanBeNull] int? port = 0, bool ssl = false)
public static WireMockServer Start(int? port = 0, bool ssl = false)
{
return new WireMockServer(new WireMockServerSettings
{
@@ -239,7 +247,7 @@ public partial class WireMockServer : IWireMockServer
if (settings.CustomCertificateDefined)
{
_options.X509StoreName = settings.CertificateSettings.X509StoreName;
_options.X509StoreName = settings.CertificateSettings!.X509StoreName;
_options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
_options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
_options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
@@ -308,7 +316,7 @@ public partial class WireMockServer : IWireMockServer
Given(Request.Create().WithPath("/*").UsingAnyMethod())
.WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05"))
.AtPriority(1000)
.RespondWith(new DynamicResponseProvider(request => ResponseMessageBuilder.Create("No matching mapping found", 404)));
.RespondWith(new DynamicResponseProvider(_ => ResponseMessageBuilder.Create("No matching mapping found", 404)));
}
/// <inheritdoc cref="IWireMockServer.Reset" />
@@ -373,7 +381,7 @@ public partial class WireMockServer : IWireMockServer
Guard.NotNull(audience, nameof(audience));
#if NETSTANDARD1_3
throw new NotSupportedException("AzureADAuthentication is not supported for NETStandard 1.3");
throw new NotSupportedException("AzureADAuthentication is not supported for NETStandard 1.3");
#else
_options.AuthenticationMatcher = new AzureADAuthenticationMatcher(tenant, audience);
#endif
@@ -381,7 +389,7 @@ public partial class WireMockServer : IWireMockServer
/// <inheritdoc cref="IWireMockServer.SetBasicAuthentication(string, string)" />
[PublicAPI]
public void SetBasicAuthentication([NotNull] string username, [NotNull] string password)
public void SetBasicAuthentication(string username, string password)
{
Guard.NotNull(username, nameof(username));
Guard.NotNull(password, nameof(password));

View File

@@ -1,24 +1,23 @@
namespace WireMock.Settings
namespace WireMock.Settings;
/// <summary>
/// HttpClientSettings
/// </summary>
public class HttpClientSettings
{
/// <summary>
/// HttpClientSettings
/// The clientCertificate thumbprint or subject name fragment to use.
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
/// </summary>
public class HttpClientSettings
{
/// <summary>
/// The clientCertificate thumbprint or subject name fragment to use.
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
/// </summary>
public string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
public string? ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
public WebProxySettings WebProxySettings { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
public WebProxySettings? WebProxySettings { get; set; }
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
public bool? AllowAutoRedirect { get; set; }
}
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
public bool? AllowAutoRedirect { get; set; }
}

View File

@@ -15,31 +15,31 @@ namespace WireMock.Settings
/// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher)
/// </summary>
[PublicAPI]
public string X509StoreName { get; set; }
public string? X509StoreName { get; set; }
/// <summary>
/// X509 StoreLocation (CurrentUser or LocalMachine)
/// </summary>
[PublicAPI]
public string X509StoreLocation { get; set; }
public string? X509StoreLocation { get; set; }
/// <summary>
/// X509 Thumbprint or SubjectName (if not defined, the 'host' is used)
/// </summary>
[PublicAPI]
public string X509StoreThumbprintOrSubjectName { get; set; }
public string? X509StoreThumbprintOrSubjectName { get; set; }
/// <summary>
/// X509Certificate FilePath
/// </summary>
[PublicAPI]
public string X509CertificateFilePath { get; set; }
public string? X509CertificateFilePath { get; set; }
/// <summary>
/// X509Certificate Password
/// </summary>
[PublicAPI]
public string X509CertificatePassword { get; set; }
public string? X509CertificatePassword { get; set; }
/// <summary>
/// X509StoreName and X509StoreLocation should be defined

View File

@@ -62,13 +62,13 @@ namespace WireMock.Settings
/// Gets or sets if the proxy and record settings.
/// </summary>
[PublicAPI]
public ProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
public ProxyAndRecordSettings? ProxyAndRecordSettings { get; set; }
/// <summary>
/// Gets or sets the urls.
/// </summary>
[PublicAPI]
public string[] Urls { get; set; }
public string[]? Urls { get; set; }
/// <summary>
/// StartTimeout
@@ -86,25 +86,25 @@ namespace WireMock.Settings
/// The username needed for __admin access.
/// </summary>
[PublicAPI]
public string AdminUsername { get; set; }
public string? AdminUsername { get; set; }
/// <summary>
/// The password needed for __admin access.
/// </summary>
[PublicAPI]
public string AdminPassword { get; set; }
public string? AdminPassword { get; set; }
/// <summary>
/// The AzureAD Tenant needed for __admin access.
/// </summary>
[PublicAPI]
public string AdminAzureADTenant { get; set; }
public string? AdminAzureADTenant { get; set; }
/// <summary>
/// The AzureAD Audience / Resource for __admin access.
/// </summary>
[PublicAPI]
public string AdminAzureADAudience { get; set; }
public string? AdminAzureADAudience { get; set; }
/// <summary>
/// The RequestLog expiration in hours (optional).
@@ -123,14 +123,14 @@ namespace WireMock.Settings
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<object> PreWireMockMiddlewareInit { get; set; }
public Action<object>? PreWireMockMiddlewareInit { get; set; }
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<object> PostWireMockMiddlewareInit { get; set; }
public Action<object>? PostWireMockMiddlewareInit { get; set; }
#if USE_ASPNETCORE
/// <summary>
@@ -138,7 +138,7 @@ namespace WireMock.Settings
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<IServiceCollection> AdditionalServiceRegistration { get; set; }
public Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
/// <summary>
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
@@ -152,21 +152,21 @@ namespace WireMock.Settings
/// </summary>
[PublicAPI]
[JsonIgnore]
public IWireMockLogger Logger { get; set; }
public IWireMockLogger Logger { get; set; } = null!;
/// <summary>
/// Handler to interact with the file system to read and write static mapping files.
/// </summary>
[PublicAPI]
[JsonIgnore]
public IFileSystemHandler FileSystemHandler { get; set; }
public IFileSystemHandler FileSystemHandler { get; set; } = null!;
/// <summary>
/// Action which can be used to add additional Handlebars registrations. [Optional]
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
public Action<IHandlebars, IFileSystemHandler>? HandlebarsRegistrationCallback { get; set; }
/// <summary>
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
@@ -220,7 +220,7 @@ namespace WireMock.Settings
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
[PublicAPI]
public WireMockCertificateSettings CertificateSettings { get; set; }
public WireMockCertificateSettings? CertificateSettings { get; set; }
/// <summary>
/// Defines if custom CertificateSettings are defined
@@ -232,7 +232,7 @@ namespace WireMock.Settings
/// Defines the global IWebhookSettings to use.
/// </summary>
[PublicAPI]
public WebhookSettings WebhookSettings { get; set; }
public WebhookSettings? WebhookSettings { get; set; }
/// <summary>
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to true).
@@ -250,6 +250,6 @@ namespace WireMock.Settings
/// Custom matcher mappings for static mappings
/// </summary>
[PublicAPI, JsonIgnore]
public IDictionary<string, Func<MatcherModel, IMatcher>> CustomMatcherMappings { get; set; }
public IDictionary<string, Func<MatcherModel, IMatcher>>? CustomMatcherMappings { get; set; }
}
}

View File

@@ -7,8 +7,8 @@ namespace WireMock.Transformers
{
interface ITransformer
{
ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
ResponseMessage Transform(IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options);
(IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers, ReplaceNodeOptions options);
(IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers, ReplaceNodeOptions options);
}
}

View File

@@ -18,7 +18,7 @@ namespace WireMock.Transformers
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
}
public (IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(RequestMessage originalRequestMessage, ResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers, ReplaceNodeOptions options)
public (IBodyData BodyData, IDictionary<string, WireMockList<string>> Headers) Transform(IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData bodyData, IDictionary<string, WireMockList<string>> headers, ReplaceNodeOptions options)
{
var transformerContext = _factory.Create();
@@ -37,7 +37,7 @@ namespace WireMock.Transformers
return (newBodyData, TransformHeaders(transformerContext, model, headers));
}
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
public ResponseMessage Transform(IRequestMessage requestMessage, IResponseMessage original, bool useTransformerForBodyAsFile, ReplaceNodeOptions options)
{
var transformerContext = _factory.Create();

View File

@@ -1,213 +1,220 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WireMock.Pact.Models.V2;
using WireMock.Serialization;
namespace WireMock.Util
namespace WireMock.Util;
internal static class JsonUtils
{
internal static class JsonUtils
public static bool TryParseAsComplexObject(string strInput, [NotNullWhen(true)] out JToken? token)
{
public static bool TryParseAsComplexObject(string strInput, out JToken token)
token = null;
if (string.IsNullOrWhiteSpace(strInput))
{
token = null;
if (string.IsNullOrWhiteSpace(strInput))
{
return false;
}
strInput = strInput.Trim();
if ((!strInput.StartsWith("{") || !strInput.EndsWith("}")) && (!strInput.StartsWith("[") || !strInput.EndsWith("]")))
{
return false;
}
try
{
// Try to convert this string into a JToken
token = JToken.Parse(strInput);
return true;
}
catch
{
return false;
}
return false;
}
public static string Serialize<T>(T value)
strInput = strInput.Trim();
if ((!strInput.StartsWith("{") || !strInput.EndsWith("}")) && (!strInput.StartsWith("[") || !strInput.EndsWith("]")))
{
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues);
return false;
}
/// <summary>
/// Load a Newtonsoft.Json.Linq.JObject from a string that contains JSON.
/// Using : DateParseHandling = DateParseHandling.None
/// </summary>
/// <param name="json">A System.String that contains JSON.</param>
/// <returns>A Newtonsoft.Json.Linq.JToken populated from the string that contains JSON.</returns>
public static JToken Parse(string json)
try
{
return JsonConvert.DeserializeObject<JToken>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone);
// Try to convert this string into a JToken
token = JToken.Parse(strInput);
return true;
}
/// <summary>
/// Deserializes the JSON to a .NET object.
/// Using : DateParseHandling = DateParseHandling.None
/// </summary>
/// <param name="json">A System.String that contains JSON.</param>
/// <returns>The deserialized object from the JSON string.</returns>
public static object DeserializeObject(string json)
catch
{
return JsonConvert.DeserializeObject(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone);
}
/// <summary>
/// Deserializes the JSON to the specified .NET type.
/// Using : DateParseHandling = DateParseHandling.None
/// </summary>
/// <param name="json">A System.String that contains JSON.</param>
/// <returns>The deserialized object from the JSON string.</returns>
public static T DeserializeObject<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone);
}
public static T ParseJTokenToObject<T>(object value)
{
switch (value)
{
case JToken tokenValue:
return tokenValue.ToObject<T>();
default:
return default(T);
}
}
public static string GenerateDynamicLinqStatement(JToken jsonObject)
{
var lines = new List<string>();
WalkNode(jsonObject, null, null, lines);
return lines.First();
}
private static void WalkNode(JToken node, string path, string propertyName, List<string> lines)
{
if (node.Type == JTokenType.Object)
{
ProcessObject(node, propertyName, lines);
}
else if (node.Type == JTokenType.Array)
{
ProcessArray(node, propertyName, lines);
}
else
{
ProcessItem(node, path ?? "it", propertyName, lines);
}
}
private static void ProcessObject(JToken node, string propertyName, List<string> lines)
{
var items = new List<string>();
var text = new StringBuilder("new (");
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JProperty child in node.Children<JProperty>().ToArray())
{
WalkNode(child.Value, child.Path, child.Name, items);
}
text.Append(string.Join(", ", items));
text.Append(")");
if (!string.IsNullOrEmpty(propertyName))
{
text.AppendFormat(" as {0}", propertyName);
}
lines.Add(text.ToString());
}
private static void ProcessArray(JToken node, string propertyName, List<string> lines)
{
var items = new List<string>();
var text = new StringBuilder("(new [] { ");
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
int idx = 0;
foreach (JToken child in node.Children().ToArray())
{
WalkNode(child, $"{node.Path}[{idx}]", null, items);
idx++;
}
text.Append(string.Join(", ", items));
text.Append("})");
if (!string.IsNullOrEmpty(propertyName))
{
text.AppendFormat(" as {0}", propertyName);
}
lines.Add(text.ToString());
}
private static void ProcessItem(JToken node, string path, string propertyName, List<string> lines)
{
string castText;
switch (node.Type)
{
case JTokenType.Boolean:
castText = $"bool({path})";
break;
case JTokenType.Date:
castText = $"DateTime({path})";
break;
case JTokenType.Float:
castText = $"double({path})";
break;
case JTokenType.Guid:
castText = $"Guid({path})";
break;
case JTokenType.Integer:
castText = $"long({path})";
break;
case JTokenType.Null:
castText = "null";
break;
case JTokenType.String:
castText = $"string({path})";
break;
case JTokenType.TimeSpan:
castText = $"TimeSpan({path})";
break;
case JTokenType.Uri:
castText = $"Uri({path})";
break;
default:
throw new NotSupportedException($"JTokenType '{node.Type}' cannot be converted to a Dynamic Linq cast operator.");
}
if (!string.IsNullOrEmpty(propertyName))
{
castText += $" as {propertyName}";
}
lines.Add(castText);
return false;
}
}
public static string Serialize(object value)
{
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues);
}
public static byte[] SerializeAsPactFile(object value)
{
var json = JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsPact);
return Encoding.UTF8.GetBytes(json);
}
/// <summary>
/// Load a Newtonsoft.Json.Linq.JObject from a string that contains JSON.
/// Using : DateParseHandling = DateParseHandling.None
/// </summary>
/// <param name="json">A System.String that contains JSON.</param>
/// <returns>A Newtonsoft.Json.Linq.JToken populated from the string that contains JSON.</returns>
public static JToken Parse(string json)
{
return JsonConvert.DeserializeObject<JToken>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone);
}
/// <summary>
/// Deserializes the JSON to a .NET object.
/// Using : DateParseHandling = DateParseHandling.None
/// </summary>
/// <param name="json">A System.String that contains JSON.</param>
/// <returns>The deserialized object from the JSON string.</returns>
public static object DeserializeObject(string json)
{
return JsonConvert.DeserializeObject(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone);
}
/// <summary>
/// Deserializes the JSON to the specified .NET type.
/// Using : DateParseHandling = DateParseHandling.None
/// </summary>
/// <param name="json">A System.String that contains JSON.</param>
/// <returns>The deserialized object from the JSON string.</returns>
public static T DeserializeObject<T>(string json)
{
return JsonConvert.DeserializeObject<T>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone);
}
public static T ParseJTokenToObject<T>(object value)
{
switch (value)
{
case JToken tokenValue:
return tokenValue.ToObject<T>();
default:
return default(T);
}
}
public static string GenerateDynamicLinqStatement(JToken jsonObject)
{
var lines = new List<string>();
WalkNode(jsonObject, null, null, lines);
return lines.First();
}
private static void WalkNode(JToken node, string? path, string? propertyName, List<string> lines)
{
if (node.Type == JTokenType.Object)
{
ProcessObject(node, propertyName, lines);
}
else if (node.Type == JTokenType.Array)
{
ProcessArray(node, propertyName, lines);
}
else
{
ProcessItem(node, path ?? "it", propertyName, lines);
}
}
private static void ProcessObject(JToken node, string? propertyName, List<string> lines)
{
var items = new List<string>();
var text = new StringBuilder("new (");
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
foreach (JProperty child in node.Children<JProperty>().ToArray())
{
WalkNode(child.Value, child.Path, child.Name, items);
}
text.Append(string.Join(", ", items));
text.Append(")");
if (!string.IsNullOrEmpty(propertyName))
{
text.AppendFormat(" as {0}", propertyName);
}
lines.Add(text.ToString());
}
private static void ProcessArray(JToken node, string? propertyName, List<string> lines)
{
var items = new List<string>();
var text = new StringBuilder("(new [] { ");
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
int idx = 0;
foreach (JToken child in node.Children().ToArray())
{
WalkNode(child, $"{node.Path}[{idx}]", null, items);
idx++;
}
text.Append(string.Join(", ", items));
text.Append("})");
if (!string.IsNullOrEmpty(propertyName))
{
text.AppendFormat(" as {0}", propertyName);
}
lines.Add(text.ToString());
}
private static void ProcessItem(JToken node, string path, string propertyName, List<string> lines)
{
string castText;
switch (node.Type)
{
case JTokenType.Boolean:
castText = $"bool({path})";
break;
case JTokenType.Date:
castText = $"DateTime({path})";
break;
case JTokenType.Float:
castText = $"double({path})";
break;
case JTokenType.Guid:
castText = $"Guid({path})";
break;
case JTokenType.Integer:
castText = $"long({path})";
break;
case JTokenType.Null:
castText = "null";
break;
case JTokenType.String:
castText = $"string({path})";
break;
case JTokenType.TimeSpan:
castText = $"TimeSpan({path})";
break;
case JTokenType.Uri:
castText = $"Uri({path})";
break;
default:
throw new NotSupportedException($"JTokenType '{node.Type}' cannot be converted to a Dynamic Linq cast operator.");
}
if (!string.IsNullOrEmpty(propertyName))
{
castText += $" as {propertyName}";
}
lines.Add(castText);
}
}

View File

@@ -2,29 +2,28 @@ using Nelibur.ObjectMapper;
using WireMock.Admin.Settings;
using WireMock.Settings;
namespace WireMock.Util
namespace WireMock.Util;
internal sealed class TinyMapperUtils
{
internal sealed class TinyMapperUtils
public static TinyMapperUtils Instance { get; } = new();
private TinyMapperUtils()
{
public static TinyMapperUtils Instance { get; } = new TinyMapperUtils();
TinyMapper.Bind<ProxyAndRecordSettings, ProxyAndRecordSettingsModel>();
TinyMapper.Bind<WebProxySettings, WebProxySettingsModel>();
private TinyMapperUtils()
{
TinyMapper.Bind<ProxyAndRecordSettings, ProxyAndRecordSettingsModel>();
TinyMapper.Bind<WebProxySettings, WebProxySettingsModel>();
TinyMapper.Bind<ProxyAndRecordSettingsModel, ProxyAndRecordSettings>();
TinyMapper.Bind<WebProxySettingsModel, WebProxySettings>();
}
TinyMapper.Bind<ProxyAndRecordSettingsModel, ProxyAndRecordSettings>();
TinyMapper.Bind<WebProxySettingsModel, WebProxySettings>();
}
public ProxyAndRecordSettingsModel? Map(ProxyAndRecordSettings? instance)
{
return instance == null ? null : TinyMapper.Map<ProxyAndRecordSettingsModel>(instance);
}
public ProxyAndRecordSettingsModel Map(ProxyAndRecordSettings instance)
{
return instance == null ? null : TinyMapper.Map<ProxyAndRecordSettingsModel>(instance);
}
public ProxyAndRecordSettings Map(ProxyAndRecordSettingsModel model)
{
return model == null ? null : TinyMapper.Map<ProxyAndRecordSettings>(model);
}
public ProxyAndRecordSettings? Map(ProxyAndRecordSettingsModel? model)
{
return model == null ? null : TinyMapper.Map<ProxyAndRecordSettings>(model);
}
}

View File

@@ -52,6 +52,7 @@
<ItemGroup>
<Compile Remove="Util\FileSystemWatcherExtensions.cs" />
<Compile Remove="Matchers\Request\IRequestMatcher.cs" />
</ItemGroup>
<ItemGroup>
@@ -88,6 +89,7 @@
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
<!--<PackageReference Include="Mapster" Version="7.2.0" />-->
<PackageReference Include="Nullable" Version="1.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
@@ -98,11 +100,13 @@
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
<PackageReference Include="Nullable" Version="1.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net461' ">
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Nullable" Version="1.3.0" />
<!-- https://github.com/WireMock-Net/WireMock.Net/issues/697 -->
<PackageReference Include="System.Text.Encodings.Web" Version="4.7.2" />
@@ -112,17 +116,20 @@
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="System.Collections.Specialized" Version="4.3.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.7" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Https" Version="1.1.3" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="Scriban.Signed" Version="2.1.4" />
<PackageReference Include="Nullable" Version="1.3.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' ">
<PackageReference Include="Scriban.Signed" Version="3.3.2" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Nullable" Version="1.3.0" />
<!-- https://github.com/WireMock-Net/WireMock.Net/issues/507 -->
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
@@ -133,6 +140,12 @@
<PackageReference Include="Scriban.Signed" Version="3.3.2" />
</ItemGroup>
<ItemGroup>
<Compile Update="Server\WireMockServer.*.cs">
<DependentUpon>WireMockServer.cs</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.3.3" />
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.3.3" />