diff --git a/src/ReC.API/appsettings.json b/src/ReC.API/appsettings.json index 70bc27d..9243a2d 100644 --- a/src/ReC.API/appsettings.json +++ b/src/ReC.API/appsettings.json @@ -10,8 +10,8 @@ "EnableDetailedErrors": false }, "RecAction": { - "AddedWho": "ReC.API", - "UseHttp1ForNtlm": false + "UseHttp1ForNtlm": false, + "AutoDetectHeaders": false }, // Bad request SqlException numbers numbers can be updated at runtime; no restart required. "SqlException": { diff --git a/src/ReC.Application/Common/Options/RecActionOptions.cs b/src/ReC.Application/Common/Options/RecActionOptions.cs index 181f0ae..3e4fa06 100644 --- a/src/ReC.Application/Common/Options/RecActionOptions.cs +++ b/src/ReC.Application/Common/Options/RecActionOptions.cs @@ -3,4 +3,5 @@ public class RecActionOptions { public bool UseHttp1ForNtlm { get; set; } = false; + public bool AutoDetectHeaders { get; set; } = false; } \ No newline at end of file diff --git a/src/ReC.Application/RecActions/Commands/InvokeRecActionViewCommand.cs b/src/ReC.Application/RecActions/Commands/InvokeRecActionViewCommand.cs index 5118f0e..53c926d 100644 --- a/src/ReC.Application/RecActions/Commands/InvokeRecActionViewCommand.cs +++ b/src/ReC.Application/RecActions/Commands/InvokeRecActionViewCommand.cs @@ -70,6 +70,20 @@ public class InvokeRecActionViewCommandHandler( logger?.LogWarning(ex, "Content-Type '{Value}' could not be parsed with strict validation, falling back to TryAddWithoutValidation. ActionId: {ActionId}, ProfileId: {ProfileId}", contentType.Value.Value, action.Id, action.ProfileId); httpReq.Content.Headers.TryAddWithoutValidation("Content-Type", contentType.Value.Value); } + else if (_options.AutoDetectHeaders) + { + var body = action.Body.TrimStart(); + if (body.StartsWith('{') || body.StartsWith('[')) + { + httpReq.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json") { CharSet = "utf-8" }; + logger?.LogWarning("Content-Type header was not specified. Auto-detected 'application/json; charset=utf-8' based on body content. ActionId: {ActionId}, ProfileId: {ProfileId}", action.Id, action.ProfileId); + } + else if (body.StartsWith('<')) + { + httpReq.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xml") { CharSet = "utf-8" }; + logger?.LogWarning("Content-Type header was not specified. Auto-detected 'application/xml; charset=utf-8' based on body content. ActionId: {ActionId}, ProfileId: {ProfileId}", action.Id, action.ProfileId); + } + } } if (action.Headers is not null) @@ -81,6 +95,12 @@ public class InvokeRecActionViewCommandHandler( httpReq.Headers.TryAddWithoutValidation(header.Key, header.Value); } + if (_options.AutoDetectHeaders && !httpReq.Headers.Contains("Accept")) + { + httpReq.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + logger?.LogWarning("Accept header was not specified. Defaulting to 'application/json'. ActionId: {ActionId}, ProfileId: {ProfileId}", action.Id, action.ProfileId); + } + switch (action.EndpointAuthType) { case EndpointAuthType.NoAuth: