80 lines
2.8 KiB
C#
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();
|
|
}
|