2024-05-11 15:26:47 +02:00
using System.Net.Http.Headers ;
using Newtonsoft.Json ;
using Newtonsoft.Json.Serialization ;
namespace Foxchat.Core.Federation ;
public partial class RequestSigningService
{
public const string USER_AGENT_HEADER = "User-Agent" ;
public const string USER_AGENT = "Foxchat.NET" ;
public const string DATE_HEADER = "Date" ;
public const string SERVER_HEADER = "X-Foxchat-Server" ;
public const string SIGNATURE_HEADER = "X-Foxchat-Signature" ;
public const string USER_HEADER = "X-Foxchat-User" ;
public async Task < T > RequestAsync < T > ( HttpMethod method , string domain , string requestPath , string? userId = null , object? body = null )
{
var request = BuildHttpRequest ( method , domain , requestPath , userId , body ) ;
var resp = await _httpClient . SendAsync ( request ) ;
if ( ! resp . IsSuccessStatusCode )
{
var error = await resp . Content . ReadAsStringAsync ( ) ;
2024-05-20 19:42:04 +02:00
throw new ApiError . OutgoingFederationError ( $"Request to {domain}{requestPath} returned an error" , JsonConvert . DeserializeObject < Models . Http . ApiError > ( error ) ) ;
2024-05-11 15:26:47 +02:00
}
var bodyString = await resp . Content . ReadAsStringAsync ( ) ;
2024-05-20 19:42:04 +02:00
return JsonConvert . DeserializeObject < T > ( bodyString )
2024-05-20 17:00:21 +02:00
? ? throw new ApiError . OutgoingFederationError ( $"Request to {domain}{requestPath} returned invalid response body" ) ;
2024-05-11 15:26:47 +02:00
}
private HttpRequestMessage BuildHttpRequest ( HttpMethod method , string domain , string requestPath , string? userId = null , object? bodyData = null )
{
2024-05-20 19:42:04 +02:00
var body = bodyData ! = null ? JsonConvert . SerializeObject ( bodyData ) : null ;
2024-05-11 15:26:47 +02:00
var now = _clock . GetCurrentInstant ( ) ;
var url = $"https://{domain}{requestPath}" ;
var signature = GenerateSignature ( new SignatureData ( now , domain , requestPath , body ? . Length , userId ) ) ;
var request = new HttpRequestMessage ( method , url ) ;
request . Headers . Clear ( ) ;
request . Headers . Add ( USER_AGENT_HEADER , USER_AGENT ) ;
request . Headers . Add ( DATE_HEADER , FormatTime ( now ) ) ;
request . Headers . Add ( SERVER_HEADER , _config . Domain ) ;
request . Headers . Add ( SIGNATURE_HEADER , signature ) ;
if ( userId ! = null )
request . Headers . Add ( USER_HEADER , userId ) ;
if ( body ! = null )
request . Content = new StringContent ( body , new MediaTypeHeaderValue ( "application/json" , "utf-8" ) ) ;
return request ;
}
}