1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Diagnostics . CodeAnalysis ;
3
4
using System . Linq ;
4
5
using System . Net . Http ;
6
+ using System . Threading ;
5
7
using System . Threading . Tasks ;
6
8
using Stef . Validation ;
7
9
using WireMock . Models ;
@@ -17,6 +19,7 @@ namespace WireMock.Http;
17
19
internal class WebhookSender
18
20
{
19
21
private const string ClientIp = "::1" ;
22
+ private static readonly ThreadLocal < Random > Random = new ( ( ) => new Random ( DateTime . UtcNow . Millisecond ) ) ;
20
23
21
24
private readonly WireMockServerSettings _settings ;
22
25
@@ -25,20 +28,26 @@ public WebhookSender(WireMockServerSettings settings)
25
28
_settings = Guard . NotNull ( settings ) ;
26
29
}
27
30
28
- public Task < HttpResponseMessage > SendAsync ( HttpClient client , IMapping mapping , IWebhookRequest request , IRequestMessage originalRequestMessage , IResponseMessage originalResponseMessage )
31
+ public async Task < HttpResponseMessage > SendAsync (
32
+ HttpClient client ,
33
+ IMapping mapping ,
34
+ IWebhookRequest webhookRequest ,
35
+ IRequestMessage originalRequestMessage ,
36
+ IResponseMessage originalResponseMessage
37
+ )
29
38
{
30
39
Guard . NotNull ( client ) ;
31
40
Guard . NotNull ( mapping ) ;
32
- Guard . NotNull ( request ) ;
41
+ Guard . NotNull ( webhookRequest ) ;
33
42
Guard . NotNull ( originalRequestMessage ) ;
34
43
Guard . NotNull ( originalResponseMessage ) ;
35
44
36
45
IBodyData ? bodyData ;
37
46
IDictionary < string , WireMockList < string > > ? headers ;
38
- if ( request . UseTransformer == true )
47
+ if ( webhookRequest . UseTransformer == true )
39
48
{
40
49
ITransformer responseMessageTransformer ;
41
- switch ( request . TransformerType )
50
+ switch ( webhookRequest . TransformerType )
42
51
{
43
52
case TransformerType . Handlebars :
44
53
var factoryHandlebars = new HandlebarsContextFactory ( _settings . FileSystemHandler , _settings . HandlebarsRegistrationCallback ) ;
@@ -47,26 +56,26 @@ public Task<HttpResponseMessage> SendAsync(HttpClient client, IMapping mapping,
47
56
48
57
case TransformerType . Scriban :
49
58
case TransformerType . ScribanDotLiquid :
50
- var factoryDotLiquid = new ScribanContextFactory ( _settings . FileSystemHandler , request . TransformerType ) ;
59
+ var factoryDotLiquid = new ScribanContextFactory ( _settings . FileSystemHandler , webhookRequest . TransformerType ) ;
51
60
responseMessageTransformer = new Transformer ( factoryDotLiquid ) ;
52
61
break ;
53
62
54
63
default :
55
- throw new NotImplementedException ( $ "TransformerType '{ request . TransformerType } ' is not supported.") ;
64
+ throw new NotImplementedException ( $ "TransformerType '{ webhookRequest . TransformerType } ' is not supported.") ;
56
65
}
57
66
58
- ( bodyData , headers ) = responseMessageTransformer . Transform ( mapping , originalRequestMessage , originalResponseMessage , request . BodyData , request . Headers , request . TransformerReplaceNodeOptions ) ;
67
+ ( bodyData , headers ) = responseMessageTransformer . Transform ( mapping , originalRequestMessage , originalResponseMessage , webhookRequest . BodyData , webhookRequest . Headers , webhookRequest . TransformerReplaceNodeOptions ) ;
59
68
}
60
69
else
61
70
{
62
- bodyData = request . BodyData ;
63
- headers = request . Headers ;
71
+ bodyData = webhookRequest . BodyData ;
72
+ headers = webhookRequest . Headers ;
64
73
}
65
74
66
75
// Create RequestMessage
67
76
var requestMessage = new RequestMessage (
68
- new UrlDetails ( request . Url ) ,
69
- request . Method ,
77
+ new UrlDetails ( webhookRequest . Url ) ,
78
+ webhookRequest . Method ,
70
79
ClientIp ,
71
80
bodyData ,
72
81
headers ? . ToDictionary ( x => x . Key , x => x . Value . ToArray ( ) )
@@ -76,9 +85,30 @@ public Task<HttpResponseMessage> SendAsync(HttpClient client, IMapping mapping,
76
85
} ;
77
86
78
87
// Create HttpRequestMessage
79
- var httpRequestMessage = HttpRequestMessageHelper . Create ( requestMessage , request . Url ) ;
88
+ var httpRequestMessage = HttpRequestMessageHelper . Create ( requestMessage , webhookRequest . Url ) ;
89
+
90
+ // Delay (if required)
91
+ if ( TryGetDelay ( webhookRequest , out var delay ) )
92
+ {
93
+ await Task . Delay ( delay . Value ) . ConfigureAwait ( false ) ;
94
+ }
80
95
81
96
// Call the URL
82
- return client . SendAsync ( httpRequestMessage ) ;
97
+ return await client . SendAsync ( httpRequestMessage ) . ConfigureAwait ( false ) ;
98
+ }
99
+
100
+ private static bool TryGetDelay ( IWebhookRequest webhookRequest , [ NotNullWhen ( true ) ] out int ? delay )
101
+ {
102
+ delay = webhookRequest . Delay ;
103
+ var minimumDelay = webhookRequest . MinimumRandomDelay ;
104
+ var maximumDelay = webhookRequest . MaximumRandomDelay ;
105
+
106
+ if ( minimumDelay is not null && maximumDelay is not null && maximumDelay >= minimumDelay )
107
+ {
108
+ delay = Random . Value ! . Next ( minimumDelay . Value , maximumDelay . Value ) ;
109
+ return true ;
110
+ }
111
+
112
+ return delay is not null ;
83
113
}
84
114
}
0 commit comments