diff --git a/Steamfitter.Api/Infrastructure/Extensions/ApiClientsExtensions.cs b/Steamfitter.Api/Infrastructure/Extensions/ApiClientsExtensions.cs index 8d8ee56..accc120 100644 --- a/Steamfitter.Api/Infrastructure/Extensions/ApiClientsExtensions.cs +++ b/Steamfitter.Api/Infrastructure/Extensions/ApiClientsExtensions.cs @@ -16,7 +16,11 @@ public static HttpClient GetHttpClient(IHttpClientFactory httpClientFactory, str { var client = httpClientFactory.CreateClient(); client.BaseAddress = new Uri(apiUrl); - client.DefaultRequestHeaders.Add("authorization", $"{tokenResponse.TokenType} {tokenResponse.AccessToken}"); + // Only add the header if the token was passed + if (tokenResponse != null) + { + client.DefaultRequestHeaders.Add("authorization", $"{tokenResponse.TokenType} {tokenResponse.AccessToken}"); + } return client; } diff --git a/Steamfitter.Api/Infrastructure/Options/VmProcessingOptions.cs b/Steamfitter.Api/Infrastructure/Options/VmProcessingOptions.cs index 1b9bd9a..a66d4a6 100644 --- a/Steamfitter.Api/Infrastructure/Options/VmProcessingOptions.cs +++ b/Steamfitter.Api/Infrastructure/Options/VmProcessingOptions.cs @@ -19,5 +19,6 @@ public class VmTaskProcessingOptions public int TaskProcessMaxWaitSeconds { get; set; } public int ExpirationCheckSeconds { get; set; } public Dictionary ApiParameters { get; set; } + public Dictionary HttpHeaderReplacements { get; set; } } } diff --git a/Steamfitter.Api/Services/TaskExecutionService.cs b/Steamfitter.Api/Services/TaskExecutionService.cs index bbd5686..372e4ed 100644 --- a/Steamfitter.Api/Services/TaskExecutionService.cs +++ b/Steamfitter.Api/Services/TaskExecutionService.cs @@ -24,6 +24,7 @@ using Steamfitter.Api.Infrastructure.HealthChecks; using System.Data; using System.Text; +using System.Text.RegularExpressions; namespace Steamfitter.Api.Services { @@ -596,13 +597,42 @@ private async STT.Task HttpTaskTask(TaskEntity taskToExecute) HttpResponseMessage response; using (var scope = _scopeFactory.CreateScope()) { - // TODO: re-use tokens - var tokenResponse = await ApiClientsExtensions.GetToken(scope); var actionParameters = JsonSerializer.Deserialize(taskToExecute.InputString); + // TODO: re-use tokens + TokenResponse tokenResponse = null; + // If the user specified headers, assume we do not need crucible auth token + if (String.IsNullOrEmpty(actionParameters.Headers)) + { + tokenResponse = await ApiClientsExtensions.GetToken(scope); + } var url = actionParameters.Url; var client = ApiClientsExtensions.GetHttpClient(_httpClientFactory, url, tokenResponse); + if (!String.IsNullOrEmpty(actionParameters.Headers)) + { + var replacementValues = _vmTaskProcessingOptions.CurrentValue.HttpHeaderReplacements; + if (replacementValues != null) + { + var headers = JsonSerializer.Deserialize>(actionParameters.Headers); + + // look up any replacement value and replace if found + foreach (var header in headers) + { + Match output = Regex.Match(header.Value, @"\{(\w+)\}"); + if (output.Success && replacementValues.ContainsKey(output.Groups[1].Value)) + { + var value = header.Value.Replace(header.Value, replacementValues[output.Groups[1].Value]); + client.DefaultRequestHeaders.Add(header.Key, value); + } + else + { + client.DefaultRequestHeaders.Add(header.Key, header.Value); + } + } + } + } switch (taskToExecute.Action) { + case TaskAction.http_get: { response = await client.GetAsync(url); @@ -768,6 +798,6 @@ class HttpInputString { public string Url { get; set; } public string Body { get; set; } + public string Headers { get; set; } } - } diff --git a/Steamfitter.Api/appsettings.json b/Steamfitter.Api/appsettings.json index 6f3b2e0..09b8050 100644 --- a/Steamfitter.Api/appsettings.json +++ b/Steamfitter.Api/appsettings.json @@ -75,6 +75,7 @@ "TaskProcessIntervalMilliseconds": 5000, "TaskProcessMaxWaitSeconds": 120, "ExpirationCheckSeconds": 30, + "HttpHeaderReplacements": {}, "ApiParameters": {} }, "ApplicationInsights": { diff --git a/Steamfitter.Api/availableCommands.json b/Steamfitter.Api/availableCommands.json index b8d700a..de56c8d 100644 --- a/Steamfitter.Api/availableCommands.json +++ b/Steamfitter.Api/availableCommands.json @@ -507,6 +507,12 @@ "display": "Body", "hint": "The body to be passed to the POST request.", "inputType": "textArea" + }, + { + "key": "Headers", + "display": "Headers", + "hint": "Request headers", + "inputType": "textArea" } ] },