Appetere
Appetere

Reputation: 6261

Owin pipeline branches run all middleware at first stage-marker encountered

When creating an (unbranched) OWIN pipeline, stage-markers are respected.

But when using a branched pipeline (with app.Map or app.MapWhen) all middleware in each branch runs at the stage of the first stage-marker encountered.

Is there any way to use stage-markers within a branch?


To illustrate the problem I'm using a modified version of the Katana branching pipeline demo

public void Configuration(IAppBuilder app)
{
    app.Use<AddBreadCrumbMiddleware>("start-of-the-line");

    app.Map("/branch1", app1 =>
    {
        app1.Use<AddBreadCrumbMiddleware>("took-branch1");
        app1.Use<AddBreadCrumbMiddleware>("more-in-branch1");

        // Nesting paths, e.g. /branch1/branch2
        app1.Map("/branch2", app2 =>
        {
            app2.Use<AddBreadCrumbMiddleware>("took-branch2");
            app2.Use<DisplayBreadCrumbs>();
        });

        app1.Use<DisplayBreadCrumbs>();
    });

For the path: /branch1/branch2 this outputs the expected result:

start-of-the-line (stage: PreHandlerExecute), took-branch1 (stage: PreHandlerExecute), more-in-branch1 (stage: PreHandlerExecute), took-branch2 (stage: PreHandlerExecute)

Now I add some stage markers:

    app.Map("/branch1", app1 =>
    {
        app1.Use<AddBreadCrumbMiddleware>("took-branch1");
        app1.UseStageMarker(PipelineStage.Authenticate);

        app1.Use<AddBreadCrumbMiddleware>("more-in-branch1");
        app1.UseStageMarker(PipelineStage.Authorize);

        // Nesting paths, e.g. /branch1/branch2
        app1.Map("/branch2", app2 =>
        {
            app2.Use<AddBreadCrumbMiddleware>("took-branch2");
            app2.UseStageMarker(PipelineStage.PostResolveCache);
            app2.Use<DisplayBreadCrumbs>();
        });

        app1.Use<DisplayBreadCrumbs>();
    });

This time the output for the same path is:

start-of-the-line (stage: Authenticate), took-branch1 (stage: Authenticate), more-in-branch1 (stage: Authenticate), took-branch2 (stage: Authenticate)

Can anyone explain why everything runs at the Authenticate stage and whether there is a workaround to respect the other stage markers in branches?

Upvotes: 5

Views: 1166

Answers (1)

Johann
Johann

Reputation: 4373

Surfacing the comment as an answer:

By design. Stage markers are only supported in the root pipeline. Otherwise you may miss taking a branch. – Tratcher Oct 20 '15 at 1:19

So yes as the question states, "when using a branched pipeline (with app.Map or app.MapWhen) all middleware in each branch runs at the stage of the first stage-marker encountered."

With that context, a note for using SignalR: when calling one of the SignalR OWIN extensions, such as MapSignalR or RunSignalR, those explicitly set the stage marker to avoid having a session state:

// We need to make that SignalR runs before any handlers are
// mapped in the IIS pipeline so that we avoid side effects like
// session being enabled. [...]
builder.UseStageMarker(PipelineStage.PostAuthorize);

https://github.com/SignalR/SignalR/blob/2.4.1/src/Microsoft.AspNet.SignalR.Core/Owin/OwinExtensions.cs#L246

This means that if you configure SignalR in your OWIN app, _all_ requests, including non-signalr requests, will run at that same stage, without HttpContext.Current.Session or HttpContext.Current.CurrentHandler.

Upvotes: 2

Related Questions