117 lines
3.2 KiB
C#
117 lines
3.2 KiB
C#
using System.Diagnostics.CodeAnalysis;
|
|
using System.Text.Json;
|
|
using Microsoft.Extensions.Options;
|
|
using Microsoft.Net.Http.Headers;
|
|
using MoonlightServers.Daemon.Configuration;
|
|
using MoonlightServers.DaemonShared.Http;
|
|
|
|
namespace MoonlightServers.Daemon.Services;
|
|
|
|
public class RemoteService
|
|
{
|
|
private readonly IOptions<RemoteOptions> Options;
|
|
private readonly ILogger<RemoteService> Logger;
|
|
private readonly IHttpClientFactory ClientFactory;
|
|
|
|
public RemoteService(
|
|
IOptions<RemoteOptions> options,
|
|
IHttpClientFactory clientFactory,
|
|
ILogger<RemoteService> logger
|
|
)
|
|
{
|
|
Options = options;
|
|
ClientFactory = clientFactory;
|
|
Logger = logger;
|
|
}
|
|
|
|
public async Task<int> CheckReachabilityAsync()
|
|
{
|
|
try
|
|
{
|
|
var client = ClientFactory.CreateClient();
|
|
|
|
var request = CreateBaseRequest(HttpMethod.Get, "api/remote/servers/nodes/ping");
|
|
var response = await client.SendAsync(request);
|
|
|
|
return (int)response.StatusCode;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logger.LogTrace(e, "An error occured while checking if remote is reachable");
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
private HttpRequestMessage CreateBaseRequest(
|
|
[StringSyntax(StringSyntaxAttribute.Uri)]
|
|
HttpMethod method,
|
|
string endpoint
|
|
)
|
|
{
|
|
var request = new HttpRequestMessage();
|
|
|
|
request.Headers.Add(HeaderNames.Authorization, $"{Options.Value.TokenId} {Options.Value.Token}");
|
|
request.RequestUri = new Uri(new Uri(Options.Value.EndpointUrl), endpoint);
|
|
request.Method = method;
|
|
|
|
return request;
|
|
}
|
|
|
|
private async Task EnsureSuccessAsync(HttpResponseMessage message)
|
|
{
|
|
if (message.IsSuccessStatusCode)
|
|
return;
|
|
|
|
try
|
|
{
|
|
var problemDetails = await message.Content.ReadFromJsonAsync<ProblemDetails>(
|
|
SerializationContext.Default.Options
|
|
);
|
|
|
|
if (problemDetails == null)
|
|
{
|
|
// If we cant handle problem details, we handle it natively
|
|
message.EnsureSuccessStatusCode();
|
|
return;
|
|
}
|
|
|
|
// Parse into exception
|
|
throw new RemoteException(
|
|
problemDetails.Type,
|
|
problemDetails.Title,
|
|
problemDetails.Status,
|
|
problemDetails.Detail,
|
|
problemDetails.Errors
|
|
);
|
|
}
|
|
catch (JsonException)
|
|
{
|
|
// If we cant handle problem details, we handle it natively
|
|
message.EnsureSuccessStatusCode();
|
|
}
|
|
}
|
|
}
|
|
|
|
public class RemoteException : Exception
|
|
{
|
|
public string Type { get; }
|
|
public string Title { get; }
|
|
public int Status { get; }
|
|
public string? Detail { get; }
|
|
public Dictionary<string, string[]>? Errors { get; }
|
|
|
|
public RemoteException(
|
|
string type,
|
|
string title,
|
|
int status,
|
|
string? detail = null,
|
|
Dictionary<string, string[]>? errors = null)
|
|
: base(detail ?? title)
|
|
{
|
|
Type = type;
|
|
Title = title;
|
|
Status = status;
|
|
Detail = detail;
|
|
Errors = errors;
|
|
}
|
|
} |