using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
using Kyoo.Abstractions.Controllers;
using Kyoo.Abstractions.Models;
using Kyoo.Abstractions.Models.Attributes;
using Microsoft.AspNetCore.Mvc;
namespace Kyoo.Core.Controllers
{
///
/// A for http/https links.
///
[FileSystemMetadata(new[] { "http", "https" })]
public class HttpFileSystem : IFileSystem
{
///
/// The http client factory used to create clients.
///
private readonly IHttpClientFactory _clientFactory;
///
/// Create a using the given client factory.
///
/// The http client factory used to create clients.
public HttpFileSystem(IHttpClientFactory factory)
{
_clientFactory = factory;
}
///
public IActionResult FileResult(string path, bool rangeSupport = false, string type = null)
{
if (path == null)
return new NotFoundResult();
return new HttpForwardResult(new Uri(path), rangeSupport, type);
}
///
public Task GetReader(string path)
{
HttpClient client = _clientFactory.CreateClient();
return client.GetStreamAsync(path);
}
///
public async Task GetReader(string path, AsyncRef mime)
{
HttpClient client = _clientFactory.CreateClient();
HttpResponseMessage response = await client.GetAsync(path);
response.EnsureSuccessStatusCode();
mime.Value = response.Content.Headers.ContentType?.MediaType;
return await response.Content.ReadAsStreamAsync();
}
///
public Task NewFile(string path)
{
throw new NotSupportedException("An http filesystem is readonly, a new file can't be created.");
}
///
public Task CreateDirectory(string path)
{
throw new NotSupportedException("An http filesystem is readonly, a directory can't be created.");
}
///
public string Combine(params string[] paths)
{
return Path.Combine(paths);
}
///
public Task> ListFiles(string path, SearchOption options = SearchOption.TopDirectoryOnly)
{
throw new NotSupportedException("Listing files is not supported on an http filesystem.");
}
///
public Task Exists(string path)
{
throw new NotSupportedException("Checking if a file exists is not supported on an http filesystem.");
}
///
public Task GetExtraDirectory(T resource)
{
throw new NotSupportedException("Extras can not be stored inside an http filesystem.");
}
}
///
/// An to proxy an http request.
///
// TODO remove this suppress message once the class has been implemented.
[SuppressMessage("ReSharper", "NotAccessedField.Local")]
public class HttpForwardResult : IActionResult
{
///
/// The path of the request to forward.
///
private readonly Uri _path;
///
/// Should the proxied result support ranges requests?
///
private readonly bool _rangeSupport;
///
/// If not null, override the content type of the resulting request.
///
private readonly string _type;
///
/// Create a new .
///
/// The path of the request to forward.
/// Should the proxied result support ranges requests?
/// If not null, override the content type of the resulting request.
public HttpForwardResult(Uri path, bool rangeSupport, string type = null)
{
_path = path;
_rangeSupport = rangeSupport;
_type = type;
}
///
public Task ExecuteResultAsync(ActionContext context)
{
// TODO implement that, example: https://github.com/twitchax/AspNetCore.Proxy/blob/14dd0f212d7abb43ca1bf8c890d5efb95db66acb/src/Core/Extensions/Http.cs#L15
throw new NotImplementedException();
}
}
}