Почему промежуточное ПО для перезаписи URL ядра asp. net не соответствует следующему регулярному выражению? - PullRequest
2 голосов
/ 07 марта 2020

Я пытаюсь переписать простой URL в другой URL в asp. net core 3 приложении. Я использовал переписывающее устройство следующим образом

app.UseRewriter(new RewriteOptions().AddRewrite(@"^(?i)quote_request.aspx\?id=(.*)", "quote/revise/$1", skipRemainingRules: true));

Но это не соответствует и переписывает (mysite) /quote_request.aspx?id=123 в (mysite) / quote / revise / 123

Я что-то упустил? Regex идеально соответствует https://dotnetfiddle.net/vk0ZVn.

также,

app.UseRewriter(new RewriteOptions().AddRewrite(@"^(?i)quote_request.aspx(.*)", "quote/revise$1", skipRemainingRules: true));

правильно переписывает (mysite) /quote_request.aspx?id=123 в (mysite) /quote/revise?id=123.

1 Ответ

2 голосов
/ 07 марта 2020

Мне пришлось искать код RewriteRule, чтобы найти ответ. Вот фрагмент метода ApplyRule:

PathString path1 = context.HttpContext.Request.Path;
Match match = path1 != PathString.Empty ? this.InitialMatch.Match(path1.ToString().Substring(1)) : this.InitialMatch.Match(path1.ToString());
if (!match.Success)
    return;

context.HttpContext.Request.Path возвращает только /quote_request.aspx для запроса на quote_request.aspx?id=123, в то время как отсутствующая часть находится в context.HttpContext.Request.QueryString! Поэтому он просто игнорирует часть URL после ? и не применяет правило, даже если переданное регулярное выражение корректно. Поэтому, чтобы избежать пропуска запроса, вы должны написать собственный IRule на основе существующего класса RewriteRule, вот упрощенный пример:

using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Rewrite;

public class CustomRewriteRule : IRule
{
    public Regex InitialMatch { get; }

    public string Replacement { get; }

    public bool StopProcessing { get; }

    public CustomRewriteRule(string regex, string replacement, bool stopProcessing)
    {
        InitialMatch = new Regex(regex, RegexOptions.Compiled | RegexOptions.CultureInvariant);
        Replacement = replacement;
        StopProcessing = stopProcessing;
    }

    public virtual void ApplyRule(RewriteContext context)
    {
        var fullPath = context.HttpContext.Request.Path + context.HttpContext.Request.QueryString;
        var match = fullPath != string.Empty ? InitialMatch.Match(fullPath.Substring(1)) : InitialMatch.Match(fullPath);
        if (!match.Success)
            return;

        var str = match.Result(this.Replacement);
        var request = context.HttpContext.Request;
        if (StopProcessing)
            context.Result = RuleResult.SkipRemainingRules;

        request.Path = str[0] != '/' ? PathString.FromUriComponent("/" + str) : PathString.FromUriComponent(str);
        request.QueryString = QueryString.Empty;
    }
}

Использование:

var options = new RewriteOptions().Add(new CustomRewriteRule(@"^(?i)quote_request.aspx\?id=(.*)", "quote/revise/$1", true));
app.UseRewriter(options);
...