Как заполняются OwinContext.Request.Path и PathBase?

Я пишу свое собственное промежуточное ПО OWIN для потока кода авторизации OpenID Connect на основе других примеров в проекте Katana.

В рамках этого я должен создать пару URI, например URI перенаправления и URL-адрес возврата.

Другие примеры в Katana делают это путем конкатенации частей из текущего запроса, например, в CookieAuthenticationHandler

loginUri =
    Request.Scheme +
    Uri.SchemeDelimiter +
    Request.Host +
    Request.PathBase +
    Options.LoginPath +
    new QueryString(Options.ReturnUrlParameter, currentUri);

Мой вопрос в том, какие правила определяют то, что заканчивается в двух свойствах пути:

OwinContext.Request.Path
OwinContext.Request.PathBase

Я попытался проверить эти свойства, поскольку запрос проходит через разные обработчики в нижеприведенном конвейере для запроса:

"https://localhost/Client/login" // Where Client is a virtual directory in IIS

Результат:

  • В сопоставленном обработчике для /login, PathBase = "/Client/Login".
  • Но, когда запрос переходит к методу ApplyResponseChallengeAsync в моем QuillCodeFlowHandler на пути назад для одного и того же запроса, PathBase = "/Client" и Path = "/Login".

Таким образом, не зная "правил" для того, как эти значения заполняются, а затем изменились, трудно построить URI, используя их. Если кто-нибудь может объяснить, будет очень признателен.

Вывод моей конфигурации:

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
    LoginPath = new PathString("/Login")
});

app.UseQuillCodeFlowAuthentication(new QuillCodeFlowOptions());

app.Map("/login", map =>
{
   map.Run(async ctx =>
   {
     if (ctx.Authentication.User == null ||
     !ctx.Authentication.User.Identity.IsAuthenticated)
     {                        
       var authenticationProperties = new AuthenticationProperties();
       [...]
       ctx.Authentication.Challenge(authenticationProperties,
                                    QuillCodeFlowDefaults.AuthenticationType);  

спецификация OWIN дает некоторое объяснение, и метод Microsoft.Owin.Host.HttpListener.GetPathAndQuery, кажется, где исходные переменные пути заданы первоначально.

Ответ 1

При использовании конструкции

app.Map("/login", map => [...]

В этом случае используется

Owin.MapExtensions.Map

который строит экземпляр

Microsoft.Owin.Mapping.MapMiddleware

для кода, который требует выполнения.

Поведение, которое я видел, объясняется в методе Invoke этого промежуточного программного обеспечения:

public async Task Invoke(IDictionary<string, object> environment)
{
    IOwinContext context = new OwinContext(environment);

    PathString path = context.Request.Path;

    PathString remainingPath;
    if (path.StartsWithSegments(_options.PathMatch, out remainingPath))
    {
        // Update the path
        PathString pathBase = context.Request.PathBase;
        context.Request.PathBase = pathBase + _options.PathMatch;
        context.Request.Path = remainingPath;

        await _options.Branch(environment);

        context.Request.PathBase = pathBase;
        context.Request.Path = path;
    }
    else
    {
        await _next(environment);
    }
}

В основном код изменяет Path и PathBase перед запуском делегата (ожидание _options.Branch(среда)), а затем возвращает их к исходным значениям после завершения выполнения.

Следовательно, объясняется поведение, которое я видел.