85 lines
2.4 KiB
C#
85 lines
2.4 KiB
C#
using System.Diagnostics;
|
|
using System.Text.RegularExpressions;
|
|
using DOIOU.Server.Models;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
namespace DOIOU.Server.Controllers;
|
|
|
|
[Route("/")]
|
|
public class MainController : Controller
|
|
{
|
|
private readonly DataRegistry _data;
|
|
|
|
public MainController(DataRegistry data)
|
|
{
|
|
_data = data;
|
|
}
|
|
|
|
[HttpGet]
|
|
public IActionResult Index()
|
|
{
|
|
return View();
|
|
}
|
|
|
|
[HttpGet("{*doiou}")]
|
|
public async Task<IActionResult> Get(string doiou) => await Resolve(doiou);
|
|
|
|
[HttpPost]
|
|
public async Task<IActionResult> Post([FromForm] string doiou) => await Resolve(doiou);
|
|
|
|
private const string DOI_REGEX = @"^((?<scheme>[a-z]+):(\/\/)?)?(?<domain>[a-z0-9.\-]+\/)?((?<prefix>\d{1,3})\.(?<publisher>\d{4,5})\/(?<id>[\S]+[^;,.\s]))$";
|
|
|
|
[NonAction]
|
|
private async Task<IActionResult> Resolve(string doiou)
|
|
{
|
|
var match = Regex.Match(doiou, DOI_REGEX);
|
|
|
|
if (!match.Success)
|
|
{
|
|
return BadRequest("Invalid format");
|
|
}
|
|
|
|
int prefix = int.Parse(match.Groups["prefix"].Value);
|
|
int publisher = int.Parse(match.Groups["publisher"].Value);
|
|
string id = match.Groups["id"].Value;
|
|
|
|
string query = $"{prefix}.{publisher}/{id}";
|
|
|
|
// TODO further validation (use schemes?)
|
|
|
|
if (prefix == 7 || prefix == 69)
|
|
{
|
|
string? q = _data.Query(query);
|
|
return q != null ? Redirect(q) : NotFound("DOIOU not found");
|
|
}
|
|
|
|
string? urlBase = prefix switch
|
|
{
|
|
10 => "https://doi.org",
|
|
_ => null
|
|
};
|
|
|
|
if (urlBase == null)
|
|
return BadRequest($"Unsupported prefix: {prefix}");
|
|
|
|
using HttpClient client = new();
|
|
client.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "DOIOU v1.0");
|
|
|
|
var response = await client.GetAsync($"{urlBase}/{doiou}");
|
|
if (((int)response.StatusCode / 100) == 3)
|
|
{
|
|
string location = response.Headers!.Location!.ToString();
|
|
return Redirect(location);
|
|
}
|
|
|
|
//TODO: cache
|
|
|
|
return NotFound("DOIOU not found");
|
|
}
|
|
|
|
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
|
public IActionResult Error()
|
|
{
|
|
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
|
|
}
|
|
}
|