Как я могу создать перезапись URL в ASP.Net Core во время выполнения? - PullRequest
2 голосов
/ 03 мая 2019

Для создания локального дискового кэша изображений с измененным размером я пытаюсь выяснить, как я могу создать перезапись URL во время выполнения.

Примерно так:

[Route("(images/{id}.jpg")]
public IActionResult ResizeImage(int id, int height, int width)
{
    string webRoot = _env.ContentRootPath;
    var file = System.IO.Path.Combine(webRoot, $"resizedimage{id}.jpg");
    //Pseudocode:
    UrlRewriter.DoMagic($"images/{id}.jpg?height={height}&width={width}", "/resizedimage{id}.jpg")
    return File(file, "image/jpeg");
}

Клиент запрашивает /images/123.jpg?height=100&width=100 ...

Я могу создать статическую перезапись URL, которая переписывает /images/123.jpg?height=100&width=100 to /images/resizedimage.jpg (измененное изображение на диске), минуя метод действия (предположительно) ..

Как я могу сделать то же самое на лету, с чем-то вроде вышеуказанного псевдокода?

Примечание:

  • Меня не волнует первый запрос, который БУДЕТ ударить по методу действия и будет обслуживать изображение через файл результата (как показано выше), только последующие запросы к тому же URL.

  • Мне известны способы создания динамических перезаписей URL-адресов при запуске, но не во время выполнения (о чем я спрашиваю)

  • Да, я мог бы просто вернуть перенаправление в файл изображения, что также довольно эффективно - но это все еще два синхронных запроса от клиента.

  • Требуется ASP.Net Core 2+

Ответы [ 2 ]

3 голосов
/ 06 мая 2019

Самый простой способ сделать это - ввести RewriteOptions в контроллер, а затем добавить к нему правила, но RewriteOptions.Rules не является поточно-ориентированным.

Вам нужно пользовательское правило и потокобезопасная коллекция. Примерно так должно работать:

Startup:

public void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton<ImageRewriteCollection>();
    // ...
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseRewriter(new RewriteOptions().Add(new ImageRewriteRule(app.ApplicationServices.GetService<ImageRewriteCollection>())));
    // ...
}

ImageRewriteCollection:

public class ImageRewriteCollection
{
    private ConcurrentDictionary<(int id, int width, int height), string> imageRewrites
        = new ConcurrentDictionary<(int id, int width, int height), string>();

    public bool TryAdd(int id, int width, int height, string path)
        => imageRewrites.TryAdd((id, width, height), path);

    public bool TryGetValue(int id, int width, int height, out string path)
        => imageRewrites.TryGetValue((id, width, height), out path);
}

ImageRewriteRule:

public class ImageRewriteRule : IRule
{
    private readonly ImageRewriteCollection rewriteCollection;
    private readonly Regex pathRegex = new Regex("^/images/(\\d+).jpg");

    public ImageRewriteRule(ImageRewriteCollection rewriteCollection)
    {
        this.rewriteCollection = rewriteCollection;
    }

    public void ApplyRule(RewriteContext context)
    {
        var request = context.HttpContext.Request;
        var pathMatch = pathRegex.Match(request.Path.Value);
        if (pathMatch.Success)
        {
            bool isValidPath = true;
            int id = int.Parse(pathMatch.Groups[1].Value);

            int width = 0;
            int height = 0;
            string widthQuery = request.Query["width"];
            string heightQuery = request.Query["height"];

            if (widthQuery == null || !int.TryParse(widthQuery, out width))
                isValidPath = false;

            if (heightQuery == null || !int.TryParse(heightQuery, out height))
                isValidPath = false;

            if (isValidPath && rewriteCollection.TryGetValue(id, width, height, out string path))
            {
                request.Path = path;
                context.Result = RuleResult.SkipRemainingRules;
            }
        }
    }
}

Контроллер:

private readonly ImageRewriteCollection rewriteCollection;

public HomeController(ImageRewriteCollection rewriteCollection)
{
    this.rewriteCollection = rewriteCollection;
}

[Route("images/{id}.jpg")]
public IActionResult ResizeImage(int id, int width, int height)
{
    rewriteCollection.TryAdd(id, width, height, "/resizedimagepath...");
    return File();
}
0 голосов
/ 03 мая 2019

Вам нужно написать промежуточное ПО для перезаписи - https://docs.microsoft.com/en-us/aspnet/core/fundamentals/url-rewriting?view=aspnetcore-2.2

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...