Add UserAgent to IPN and webhook HTTP requests (Fix #4883)

This commit is contained in:
nicolas.dorier 2023-04-19 21:13:31 +09:00
parent feb927c2e4
commit 381fe70a79
No known key found for this signature in database
GPG key ID: 6618763EF09186FE
5 changed files with 25 additions and 4 deletions

View file

@ -1474,6 +1474,7 @@ namespace BTCPayServer.Tests
var newDeliveryId = await clientProfile.RedeliverWebhook(user.StoreId, hook.Id, delivery.Id); var newDeliveryId = await clientProfile.RedeliverWebhook(user.StoreId, hook.Id, delivery.Id);
req = await fakeServer.GetNextRequest(); req = await fakeServer.GetNextRequest();
req.Response.StatusCode = 404; req.Response.StatusCode = 404;
Assert.StartsWith("BTCPayServer", Assert.Single(req.Request.Headers.UserAgent));
await TestUtils.EventuallyAsync(async () => await TestUtils.EventuallyAsync(async () =>
{ {
// Releasing semaphore several times may help making this test less flaky // Releasing semaphore several times may help making this test less flaky

View file

@ -43,7 +43,7 @@ namespace BTCPayServer.HostedServices
readonly InvoiceRepository _InvoiceRepository; readonly InvoiceRepository _InvoiceRepository;
private readonly EmailSenderFactory _EmailSenderFactory; private readonly EmailSenderFactory _EmailSenderFactory;
private readonly StoreRepository _StoreRepository; private readonly StoreRepository _StoreRepository;
public const string NamedClient = "bitpay-ipn";
public BitpayIPNSender( public BitpayIPNSender(
IHttpClientFactory httpClientFactory, IHttpClientFactory httpClientFactory,
IBackgroundJobClient jobClient, IBackgroundJobClient jobClient,
@ -52,7 +52,7 @@ namespace BTCPayServer.HostedServices
StoreRepository storeRepository, StoreRepository storeRepository,
EmailSenderFactory emailSenderFactory) EmailSenderFactory emailSenderFactory)
{ {
_Client = httpClientFactory.CreateClient(); _Client = httpClientFactory.CreateClient(NamedClient);
_JobClient = jobClient; _JobClient = jobClient;
_EventAggregator = eventAggregator; _EventAggregator = eventAggregator;
_InvoiceRepository = invoiceRepository; _InvoiceRepository = invoiceRepository;
@ -232,7 +232,6 @@ namespace BTCPayServer.HostedServices
request.RequestUri = new Uri(notification.NotificationURL, UriKind.Absolute); request.RequestUri = new Uri(notification.NotificationURL, UriKind.Absolute);
request.Content = new StringContent(notificationString, UTF8, "application/json"); request.Content = new StringContent(notificationString, UTF8, "application/json");
using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); using CancellationTokenSource cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
cts.CancelAfter(TimeSpan.FromMinutes(1.0)); cts.CancelAfter(TimeSpan.FromMinutes(1.0));
var response = await _Client.SendAsync(request, cts.Token); var response = await _Client.SendAsync(request, cts.Token);

View file

@ -13,6 +13,7 @@ using BTCPayServer.Controllers.Greenfield;
using BTCPayServer.Data; using BTCPayServer.Data;
using BTCPayServer.Events; using BTCPayServer.Events;
using BTCPayServer.Logging; using BTCPayServer.Logging;
using BTCPayServer.Services;
using BTCPayServer.Services.Invoices; using BTCPayServer.Services.Invoices;
using BTCPayServer.Services.Stores; using BTCPayServer.Services.Stores;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -31,6 +32,7 @@ namespace BTCPayServer.HostedServices
{ {
readonly Encoding UTF8 = new UTF8Encoding(false); readonly Encoding UTF8 = new UTF8Encoding(false);
public readonly static JsonSerializerSettings DefaultSerializerSettings; public readonly static JsonSerializerSettings DefaultSerializerSettings;
static WebhookSender() static WebhookSender()
{ {
DefaultSerializerSettings = WebhookEvent.DefaultSerializerSettings; DefaultSerializerSettings = WebhookEvent.DefaultSerializerSettings;
@ -38,6 +40,7 @@ namespace BTCPayServer.HostedServices
public const string OnionNamedClient = "greenfield-webhook.onion"; public const string OnionNamedClient = "greenfield-webhook.onion";
public const string ClearnetNamedClient = "greenfield-webhook.clearnet"; public const string ClearnetNamedClient = "greenfield-webhook.clearnet";
public const string LoopbackNamedClient = "greenfield-webhook.loopback"; public const string LoopbackNamedClient = "greenfield-webhook.loopback";
public static string[] AllClients = new[] { OnionNamedClient, ClearnetNamedClient, LoopbackNamedClient };
private HttpClient GetClient(Uri uri) private HttpClient GetClient(Uri uri)
{ {
return HttpClientFactory.CreateClient(uri.IsOnion() ? OnionNamedClient : uri.IsLoopback ? LoopbackNamedClient : ClearnetNamedClient); return HttpClientFactory.CreateClient(uri.IsOnion() ? OnionNamedClient : uri.IsLoopback ? LoopbackNamedClient : ClearnetNamedClient);

View file

@ -477,6 +477,17 @@ namespace BTCPayServer.Hosting
services.AddSingleton<Cheater>(); services.AddSingleton<Cheater>();
services.AddSingleton<IHostedService, Cheater>(o => o.GetRequiredService<Cheater>()); services.AddSingleton<IHostedService, Cheater>(o => o.GetRequiredService<Cheater>());
} }
var userAgent = new System.Net.Http.Headers.ProductInfoHeaderValue("BTCPayServer", BTCPayServerEnvironment.GetInformationalVersion());
foreach (var clientName in WebhookSender.AllClients.Concat(new[] { BitpayIPNSender.NamedClient }))
{
services.AddHttpClient(clientName)
.ConfigureHttpClient(client =>
{
client.DefaultRequestHeaders.UserAgent.Add(userAgent);
});
}
return services; return services;
} }

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Net.Http;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using BTCPayServer.Configuration; using BTCPayServer.Configuration;
@ -17,7 +18,7 @@ namespace BTCPayServer.Services
readonly TorServices torServices; readonly TorServices torServices;
public BTCPayServerEnvironment(IWebHostEnvironment env, BTCPayNetworkProvider provider, TorServices torServices, BTCPayServerOptions opts) public BTCPayServerEnvironment(IWebHostEnvironment env, BTCPayNetworkProvider provider, TorServices torServices, BTCPayServerOptions opts)
{ {
Version = typeof(BTCPayServerEnvironment).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion; Version = GetInformationalVersion();
Commit = typeof(BTCPayServerEnvironment).GetTypeInfo().Assembly.GetCustomAttribute<GitCommitAttribute>()?.ShortSHA; Commit = typeof(BTCPayServerEnvironment).GetTypeInfo().Assembly.GetCustomAttribute<GitCommitAttribute>()?.ShortSHA;
#if DEBUG #if DEBUG
Build = "Debug"; Build = "Debug";
@ -35,6 +36,12 @@ namespace BTCPayServer.Services
this.torServices = torServices; this.torServices = torServices;
CheatMode = opts.CheatMode; CheatMode = opts.CheatMode;
} }
internal static string GetInformationalVersion()
{
return typeof(BTCPayServerEnvironment).GetTypeInfo().Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
}
public IWebHostEnvironment Environment public IWebHostEnvironment Environment
{ {
get; set; get; set;