using System; using System.Net.Http; using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Hangfire; using Hangfire.States; using MalwareMultiScan.Api.Services.Interfaces; using MalwareMultiScan.Shared.Message; using MalwareMultiScan.Shared.Services.Interfaces; using Microsoft.Extensions.Logging; namespace MalwareMultiScan.Api.Services { /// /// Job for storing scan results. /// public class ScanResultJob : IScanResultJob { private readonly IBackgroundJobClient _backgroundJobClient; private readonly IHttpClientFactory _httpClientFactory; private readonly ILogger _logger; private readonly IScanResultService _scanResultService; /// /// Initialize scan result storing job. /// /// Logger. /// HTTP client factory. /// Scan result service. /// Background job client. public ScanResultJob( ILogger logger, IHttpClientFactory httpClientFactory, IScanResultService scanResultService, IBackgroundJobClient backgroundJobClient) { _logger = logger; _httpClientFactory = httpClientFactory; _scanResultService = scanResultService; _backgroundJobClient = backgroundJobClient; } /// public async Task Report(string resultId, string backendId, ScanResultMessage result) { _logger.LogInformation( $"Received a result from {backendId} for {result} with status {result.Status} " + $"and threats {string.Join(",", result.Threats)}"); await _scanResultService.UpdateScanResultForBackend(resultId, backendId, result); var scanResult = await _scanResultService.GetScanResult(resultId); if (scanResult?.CallbackUrl == null) return; _backgroundJobClient.Create( x => x.Notify(scanResult.CallbackUrl, resultId, backendId, result), new EnqueuedState("default")); } /// public async Task Notify(Uri uri, string resultId, string backendId, ScanResultMessage result) { var cancellationTokenSource = new CancellationTokenSource( TimeSpan.FromSeconds(5)); using var httpClient = _httpClientFactory.CreateClient(); try { var builder = new UriBuilder(uri) { Query = $"?id={resultId}" + $"&backend={backendId}" }; var response = await httpClient.PostAsync(builder.Uri, new StringContent(JsonSerializer.Serialize(result), Encoding.UTF8, "application/json"), cancellationTokenSource.Token); response.EnsureSuccessStatusCode(); _logger.LogInformation($"Sent POST to callback URL {uri}"); } catch (Exception exception) { _logger.LogError(exception, $"Failed to POST to callback URL {uri}"); } } } }