【问题标题】:How can I create url rewrites in ASP.Net Core at runtime?如何在运行时在 ASP.Net Core 中创建 url 重写?
【发布时间】:2019-09-22 08:34:59
【问题描述】:

为了创建调整大小图像的本地磁盘缓存,我试图弄清楚如何在运行时创建 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 重写为 /images/resizedimage.jpg(磁盘上调整大小的图像),绕过操作方法(大概)..

如何使用上述伪代码即时执行相同的操作?

注意:

  • 我不关心第一个请求,它会点击 actionmethod 并通过文件结果(如上所示)提供图像,只关心对同一 url 的后续请求。

  • 我知道在启动时创建动态 url 重写的方法,但不是运行时(这是我要问的)

  • 是的,我可以只返回对图像文件的重定向,这也非常有效 - 但它仍然是来自客户端的两个同步请求。

  • 需要 ASP.Net Core 2+

【问题讨论】:

  • 我不明白如果您从操作方法提供文件,为什么要使用 url 重写。你能给我解释一下吗?
  • @ElvisJr Url 重写发生在较低级别,因此它的工作方式就像直接从 /image/myimage.jpg 提供文件一样,而从操作方法返回它需要服务器处理(即一个额外的层 - 规模变慢)。
  • 如果您寻求性能,您可能希望在服务器级别而不是应用级别设置重写规则,或者编写您的中间件来处理此问题

标签: c# asp.net-mvc asp.net-core url-rewriting asp.net-core-mvc


【解决方案1】:

最简单的方法是将RewriteOptions 注入控制器,然后向其添加规则,但RewriteOptions.Rules 不是线程安全的。

您需要自定义规则和线程安全集合。像这样的东西应该可以工作:

启动:

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();
}

【讨论】:

    【解决方案2】:

    【讨论】:

    • 据我所知,该页面上的所有示例都依赖于应用程序启动时设置的静态规则 - 不是在运行时动态添加的,因为我需要。如果我错了,请纠正我。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-23
    • 2017-09-10
    • 2017-04-27
    • 2019-02-08
    • 1970-01-01
    • 2014-12-07
    • 1970-01-01
    相关资源
    最近更新 更多