Use named HttpClients (#15375)

* Use named HttpClients

* Register as named client

* Set headers on request message.

* Add User agent header to http client

* Add headers within Try-catch

* Add using for HttpResponseMessage

* Update src/Umbraco.Infrastructure/BackgroundJobs/Jobs/WebhookFiring.cs

Co-authored-by: Ronald Barendse <ronald@barend.se>

* Update src/Umbraco.Infrastructure/BackgroundJobs/Jobs/WebhookFiring.cs

Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>

* Log key instead of entire webhook

* Update src/Umbraco.Web.Common/DependencyInjection/UmbracoBuilderExtensions.cs

Co-authored-by: Ronald Barendse <ronald@barend.se>

* Create constant for User agent header name

* Update src/Umbraco.Infrastructure/BackgroundJobs/Jobs/WebhookFiring.cs

Co-authored-by: Ronald Barendse <ronald@barend.se>

* Use datetime.now

---------

Co-authored-by: Zeegaan <nge@umbraco.dk>
Co-authored-by: Ronald Barendse <ronald@barend.se>
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
This commit is contained in:
Nikolaj Geisle
2023-12-07 09:51:44 +01:00
committed by GitHub
parent 370e1cc125
commit 4ff2572d78
4 changed files with 47 additions and 18 deletions

View File

@@ -14,5 +14,18 @@ public static partial class Constants
/// Name for http client which ignores certificate errors.
/// </summary>
public const string IgnoreCertificateErrors = "Umbraco:HttpClients:IgnoreCertificateErrors";
/// <summary>
/// Name for http client which sends webhook requests.
/// </summary>
public const string WebhookFiring = "Umbraco:HttpClients:WebhookFiring";
public static class Headers
{
/// <summary>
/// User agent name for the product name.
/// </summary>
public const string UserAgentProductName = "Umbraco-Cms";
}
}
}

View File

@@ -55,7 +55,7 @@ public abstract class OEmbedProviderBase : IEmbedProvider
if (_httpClient == null)
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd("Umbraco-CMS");
_httpClient.DefaultRequestHeaders.UserAgent.TryParseAdd(Constants.HttpClients.Headers.UserAgentProductName);
}
using (var request = new HttpRequestMessage(HttpMethod.Get, url))

View File

@@ -6,7 +6,6 @@ using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Scoping;
using Umbraco.Cms.Core.Serialization;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Infrastructure.BackgroundJobs.Jobs;
@@ -15,11 +14,11 @@ public class WebhookFiring : IRecurringBackgroundJob
{
private readonly ILogger<WebhookFiring> _logger;
private readonly IWebhookRequestService _webhookRequestService;
private readonly IJsonSerializer _jsonSerializer;
private readonly IWebhookLogFactory _webhookLogFactory;
private readonly IWebhookLogService _webhookLogService;
private readonly IWebhookService _webHookService;
private readonly ICoreScopeProvider _coreScopeProvider;
private readonly IHttpClientFactory _httpClientFactory;
private WebhookSettings _webhookSettings;
public TimeSpan Period => _webhookSettings.Period;
@@ -32,20 +31,20 @@ public class WebhookFiring : IRecurringBackgroundJob
public WebhookFiring(
ILogger<WebhookFiring> logger,
IWebhookRequestService webhookRequestService,
IJsonSerializer jsonSerializer,
IWebhookLogFactory webhookLogFactory,
IWebhookLogService webhookLogService,
IWebhookService webHookService,
IOptionsMonitor<WebhookSettings> webhookSettings,
ICoreScopeProvider coreScopeProvider)
ICoreScopeProvider coreScopeProvider,
IHttpClientFactory httpClientFactory)
{
_logger = logger;
_webhookRequestService = webhookRequestService;
_jsonSerializer = jsonSerializer;
_webhookLogFactory = webhookLogFactory;
_webhookLogService = webhookLogService;
_webHookService = webHookService;
_coreScopeProvider = coreScopeProvider;
_httpClientFactory = httpClientFactory;
_webhookSettings = webhookSettings.CurrentValue;
webhookSettings.OnChange(x => _webhookSettings = x);
}
@@ -72,8 +71,7 @@ public class WebhookFiring : IRecurringBackgroundJob
return;
}
HttpResponseMessage? response = await SendRequestAsync(webhook, request.EventAlias, request.RequestObject, request.RetryCount, CancellationToken.None);
using HttpResponseMessage? response = await SendRequestAsync(webhook, request.EventAlias, request.RequestObject, request.RetryCount, CancellationToken.None);
if ((response?.IsSuccessStatusCode ?? false) || request.RetryCount >= _webhookSettings.MaximumRetries)
{
await _webhookRequestService.DeleteAsync(request);
@@ -90,24 +88,36 @@ public class WebhookFiring : IRecurringBackgroundJob
private async Task<HttpResponseMessage?> SendRequestAsync(IWebhook webhook, string eventName, string? serializedObject, int retryCount, CancellationToken cancellationToken)
{
using var httpClient = new HttpClient();
using HttpClient httpClient = _httpClientFactory.CreateClient(Constants.HttpClients.WebhookFiring);
var stringContent = new StringContent(serializedObject ?? string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json);
stringContent.Headers.TryAddWithoutValidation("Umb-Webhook-Event", eventName);
foreach (KeyValuePair<string, string> header in webhook.Headers)
using var request = new HttpRequestMessage(HttpMethod.Post, webhook.Url)
{
stringContent.Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Version = httpClient.DefaultRequestVersion,
VersionPolicy = httpClient.DefaultVersionPolicy,
};
HttpResponseMessage? response = null;
try
{
response = await httpClient.PostAsync(webhook.Url, stringContent, cancellationToken);
// Add headers
request.Headers.Add("Umb-Webhook-Event", eventName);
request.Headers.Add("Umb-Webhook-RetryCount", retryCount.ToString());
request.Headers.Add("Umb-Webhook-Date", DateTime.Now.ToString("R"));
foreach (KeyValuePair<string, string> header in webhook.Headers)
{
request.Headers.Add(header.Key, header.Value);
}
// Set content
request.Content = new StringContent(serializedObject ?? string.Empty, Encoding.UTF8, MediaTypeNames.Application.Json);
// Send request
response = await httpClient.SendAsync(request, cancellationToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error while sending webhook request for webhook {WebhookKey}.", webhook);
_logger.LogError(ex, "Error while sending webhook request for webhook {WebhookKey}.", webhook.Key);
}
var webhookResponseModel = new WebhookResponseModel

View File

@@ -1,4 +1,5 @@
using System.Data.Common;
using System.Net.Http.Headers;
using System.Reflection;
using Dazinator.Extensions.FileProviders.GlobPatternFilter;
using Microsoft.AspNetCore.Builder;
@@ -10,7 +11,6 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Serilog.Extensions.Logging;
@@ -23,6 +23,7 @@ using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Blocks;
using Umbraco.Cms.Core.Cache;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Diagnostics;
@@ -261,6 +262,11 @@ public static partial class UmbracoBuilderExtensions
ServerCertificateCustomValidationCallback =
HttpClientHandler.DangerousAcceptAnyServerCertificateValidator,
});
builder.Services.AddHttpClient(Constants.HttpClients.WebhookFiring, (services, client) =>
{
var productVersion = services.GetRequiredService<IUmbracoVersion>().SemanticVersion.ToSemanticStringWithoutBuild();
client.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue(Constants.HttpClients.Headers.UserAgentProductName, productVersion));
});
return builder;
}