2020-10-23 11:11:19 +03:00

90 lines
3.1 KiB
C#

using System;
using System.IO;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using MalwareMultiScan.Api.Data.Models;
using Microsoft.Extensions.Logging;
using MongoDB.Driver;
using MongoDB.Driver.GridFS;
namespace MalwareMultiScan.Api.Services
{
public class ScanRequestService
{
private const string CollectionName = "ScanRequests";
private readonly GridFSBucket _bucket;
private readonly IMongoCollection<ScanRequest> _collection;
private readonly BackendConfigurationReader _configurationReader;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<ScanRequestService> _logger;
public ScanRequestService(IMongoDatabase db, BackendConfigurationReader configurationReader,
IHttpClientFactory httpClientFactory, ILogger<ScanRequestService> logger)
{
_configurationReader = configurationReader;
_httpClientFactory = httpClientFactory;
_logger = logger;
_bucket = new GridFSBucket(db);
_collection = db.GetCollection<ScanRequest>(CollectionName);
}
private async Task QueueScans(string requestId, string fileName, Stream fileStream)
{
foreach (var backend in _configurationReader.Backends)
{
var cancellationTokenSource = new CancellationTokenSource(
TimeSpan.FromSeconds(5));
using var httpClient = _httpClientFactory.CreateClient();
try
{
var endpointUri = new Uri(
new Uri(backend.Endpoint), "/scan/file");
var formContent = new MultipartFormDataContent
{
{new StringContent("value1"), "callbackUrl"},
{new StreamContent(fileStream), "inputFile", fileName}
};
var response = await httpClient.PostAsync(
endpointUri, formContent, cancellationTokenSource.Token);
response.EnsureSuccessStatusCode();
// TODO: update scan request
}
catch (Exception e)
{
_logger.LogError(e,
$"Failed to queue scanning job on {backend.Id} ({backend.Endpoint})");
}
}
}
public async Task<string> InitializeNewRequest(string fileName, Stream fileStream,
CancellationToken cancellationToken = default)
{
var fileId = await _bucket.UploadFromStreamAsync(fileName, fileStream,
cancellationToken: cancellationToken);
var scanRequest = new ScanRequest
{
FileId = fileId.ToString()
};
await _collection.InsertOneAsync(scanRequest, new InsertOneOptions
{
BypassDocumentValidation = false
}, cancellationToken);
await QueueScans(scanRequest.Id, fileName, fileStream);
return scanRequest.Id;
}
}
}