zcbot/windows-node/Zcbot.WindowsNode/Transfers/NodeHttpClient.cs

80 lines
2.8 KiB
C#

using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
namespace Zcbot.WindowsNode;
internal sealed class NodeHttpClient : IDisposable
{
private readonly HttpClient client;
internal NodeHttpClient(NodeConfig config, HttpMessageHandler? handler = null)
{
client = handler is null
? new HttpClient()
: new HttpClient(handler, disposeHandler: true);
client.BaseAddress = config.ServerUrl;
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", config.NodeToken);
client.DefaultRequestHeaders.Add("X-Node-Id", config.NodeId.ToString());
var version = Assembly.GetExecutingAssembly().GetName().Version?.ToString(3) ?? "0.1.0";
client.DefaultRequestHeaders.UserAgent.ParseAdd($"zcbot-windows-node/{version}");
}
internal HttpRequestMessage CreateRequest(
HttpMethod method,
string path,
RecoverableJob? job = null,
HttpContent? content = null)
{
var request = new HttpRequestMessage(method, path) { Content = content };
if (job is not null)
{
request.Headers.Add("X-Lease-Id", job.LeaseId.ToString());
request.Headers.Add("X-Request-Digest", job.RequestDigest);
}
return request;
}
internal Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
HttpCompletionOption completionOption = HttpCompletionOption.ResponseContentRead,
CancellationToken cancellationToken = default) =>
client.SendAsync(request, completionOption, cancellationToken);
internal async Task<HttpResponseMessage> SendWithRetryAsync(
Func<HttpRequestMessage> requestFactory,
HttpCompletionOption completionOption,
CancellationToken cancellationToken)
{
for (var attempt = 0; ; attempt++)
{
using var request = requestFactory();
try
{
var response = await SendAsync(request, completionOption, cancellationToken);
var delay = TransferRetryPolicy.RetryDelay(
request.Method, attempt, response.StatusCode);
if (delay is null)
{
return response;
}
response.Dispose();
await Task.Delay(delay.Value, cancellationToken);
}
catch (HttpRequestException exception)
{
var delay = TransferRetryPolicy.RetryDelay(
request.Method, attempt, exception: exception);
if (delay is null)
{
throw;
}
await Task.Delay(delay.Value, cancellationToken);
}
}
}
public void Dispose() => client.Dispose();
}