@@ -40,9 +40,9 @@ public class HttpCallExecutor(IServiceProvider serviceProvider, ILogger<HttpCall
40
40
protected ISerializerProvider SerializerProvider { get ; } = serializerProvider ;
41
41
42
42
/// <summary>
43
- /// Gets the service used to perform HTTP requests
43
+ /// Gets the service used to create <see cref="HttpClient"/>s
44
44
/// </summary>
45
- protected HttpClient HttpClient { get ; } = httpClientFactory . CreateClient ( ) ;
45
+ protected IHttpClientFactory HttpClientFactory { get ; } = httpClientFactory ;
46
46
47
47
/// <summary>
48
48
/// Gets the definition of the http call to perform
@@ -56,7 +56,8 @@ protected override async Task DoInitializeAsync(CancellationToken cancellationTo
56
56
{
57
57
this . Http = ( HttpCallDefinition ) this . JsonSerializer . Convert ( this . Task . Definition . With , typeof ( HttpCallDefinition ) ) ! ;
58
58
var authentication = this . Http . Endpoint . Authentication == null ? null : await this . Task . Workflow . Expressions . EvaluateAsync < AuthenticationPolicyDefinition > ( this . Http . Endpoint . Authentication , this . Task . Input , this . Task . Arguments , cancellationToken ) . ConfigureAwait ( false ) ;
59
- await this . HttpClient . ConfigureAuthenticationAsync ( authentication , this . ServiceProvider , this . Task . Workflow . Definition , cancellationToken ) . ConfigureAwait ( false ) ;
59
+ using var httpClient = this . HttpClientFactory . CreateClient ( ) ;
60
+ await httpClient . ConfigureAuthenticationAsync ( authentication , this . ServiceProvider , this . Task . Workflow . Definition , cancellationToken ) . ConfigureAwait ( false ) ;
60
61
}
61
62
catch ( Exception ex )
62
63
{
@@ -76,9 +77,7 @@ protected override async Task DoExecuteAsync(CancellationToken cancellationToken
76
77
{
77
78
if ( this . Http == null ) throw new InvalidOperationException ( "The executor must be initialized before execution" ) ;
78
79
ISerializer ? serializer ;
79
- var defaultMediaType = this . Http . Body is string
80
- ? MediaTypeNames . Text . Plain
81
- : MediaTypeNames . Application . Json ;
80
+ var defaultMediaType = this . Http . Body is string ? MediaTypeNames . Text . Plain : MediaTypeNames . Application . Json ;
82
81
if ( ( this . Http . Headers ? . TryGetValue ( "Content-Type" , out var mediaType ) != true && this . Http . Headers ? . TryGetValue ( "Content-Type" , out mediaType ) != true ) || string . IsNullOrWhiteSpace ( mediaType ) ) mediaType = defaultMediaType ;
83
82
else mediaType = mediaType . Split ( ';' , StringSplitOptions . RemoveEmptyEntries ) [ 0 ] . Trim ( ) ;
84
83
var requestContent = ( HttpContent ? ) null ;
@@ -133,9 +132,19 @@ protected override async Task DoExecuteAsync(CancellationToken cancellationToken
133
132
}
134
133
var uri = StringFormatter . NamedFormat ( this . Http . EndpointUri . OriginalString , this . Task . Input . ToDictionary ( ) ) ;
135
134
if ( uri . IsRuntimeExpression ( ) ) uri = await this . Task . Workflow . Expressions . EvaluateAsync < string > ( uri , this . Task . Input , this . GetExpressionEvaluationArguments ( ) , cancellationToken ) . ConfigureAwait ( false ) ;
135
+ using var httpClient = this . Http . Redirect ? this . HttpClientFactory . CreateClient ( ) : this . HttpClientFactory . CreateClient ( RunnerDefaults . HttpClients . NoRedirect ) ; ;
136
136
using var request = new HttpRequestMessage ( new HttpMethod ( this . Http . Method ) , uri ) { Content = requestContent } ;
137
- using var response = await this . HttpClient . SendAsync ( request , cancellationToken ) . ConfigureAwait ( false ) ;
138
- if ( ! response . IsSuccessStatusCode ) //todo: could be configurable on HTTP call?
137
+ if ( this . Http . Headers != null )
138
+ {
139
+ foreach ( var header in this . Http . Headers )
140
+ {
141
+ var headerValue = header . Value ;
142
+ if ( headerValue . IsRuntimeExpression ( ) ) headerValue = await this . Task . Workflow . Expressions . EvaluateAsync < string > ( headerValue , this . Task . Input , this . GetExpressionEvaluationArguments ( ) , cancellationToken ) . ConfigureAwait ( false ) ;
143
+ request . Headers . TryAddWithoutValidation ( header . Key , headerValue ) ;
144
+ }
145
+ }
146
+ using var response = await httpClient . SendAsync ( request , cancellationToken ) . ConfigureAwait ( false ) ;
147
+ if ( ! response . IsSuccessStatusCode )
139
148
{
140
149
var detail = await response . Content . ReadAsStringAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
141
150
this . Logger . LogError ( "Failed to request '{method} {uri}'. The remote server responded with a non-success status code '{statusCode}'." , this . Http . Method , uri , response . StatusCode ) ;
@@ -185,18 +194,4 @@ protected override async Task DoExecuteAsync(CancellationToken cancellationToken
185
194
await this . SetResultAsync ( result , this . Task . Definition . Then , cancellationToken ) . ConfigureAwait ( false ) ;
186
195
}
187
196
188
- /// <inheritdoc/>
189
- protected override async ValueTask DisposeAsync ( bool disposing )
190
- {
191
- await base . DisposeAsync ( disposing ) . ConfigureAwait ( false ) ;
192
- this . HttpClient . Dispose ( ) ;
193
- }
194
-
195
- /// <inheritdoc/>
196
- protected override void Dispose ( bool disposing )
197
- {
198
- base . Dispose ( disposing ) ;
199
- this . HttpClient . Dispose ( ) ;
200
- }
201
-
202
197
}
0 commit comments