---
title: App startup configure pipeline
summary: AppStartup.Configure assembles the HTTP request pipeline for web applications.
status: draft
owner: Framework.NCore maintainers
last_reviewed: 2026-10-02
library: SAIF.NetCore.ServiceExtensions
reference_type: package
operation_id: OP-15
trigger: ASP.NET Core calls Configure on an AppStartup-derived class during host startup.
---

# App startup configure pipeline

This operation assembles the HTTP request pipeline for web applications: request buffering, session, error/debug handling, authentication, OIDC-related middleware, HSTS/HTTPS redirection, static files, routing, authorization, and application-specific UI wiring.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-15 |
| **Trigger** | The ASP.NET Core host calls `Configure(IApplicationBuilder app, IWebHostEnvironment env)` on an `AppStartup`-derived class. |
| **Inputs** | The `IApplicationBuilder`; `AppStartup`'s instance flags. |
| **Outputs** | A fully composed HTTP request pipeline. |
| **Primary components** | `AppStartup.Configure` |
| **Entry point** | `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs` (L144–190) |

## Steps

1. Register a lambda that calls `Request.EnableBuffering()` for every request.
2. If `EnableSessionMiddleware`: `UseSession()`, `UseMiddleware<AspNetSessionIdMiddleware>()` ([BR-SE-17](../business-rules.md#br-se-17-session-support-and-its-gate-are-opt-in))
   - See [Legacy cookie gate middleware](legacy-cookie-gate-middleware.md) for `AspNetSessionIdMiddleware`'s fail-open behavior.
3. `ConfigureErrorHandling().ConfigureDebugRequestHandling()` wires [Dynamic error handler invocation](dynamic-error-handler-invoke.md) and [Debug request handler invocation](debug-request-handler-invoke.md) ([BR-SE-13](../business-rules.md#br-se-13-exception-to-http-response-mapping))
4. `UseAuthentication()`.
5. If `HostLocation == External`: `LowerCaseUrlMiddleware` is wired only if `AuthenticationChallengeType == OpenIdConnect`; `JwtClaimMiddleware` is wired unconditionally (and runs after `LowerCaseUrlMiddleware` when both are present); `RefreshJwtMiddleware` is wired only if `UseJwtRefreshMiddleware` — the three conditions are independent, but pipeline order is fixed as lower-case URL, then JWT claims, then refresh ([BR-SE-10](../business-rules.md#br-se-10-jwt-refresh-and-lower-case-url-middleware-are-conditionally-registered))

   > **Origin**: `JwtClaimMiddleware` and `RefreshJwtMiddleware`'s own request-handling logic is implemented in [`Sync JWT claims`](../../saif-netcore-oidc/operations/op-05-sync-jwt-claims.md) and [`Refresh tokens`](../../saif-netcore-oidc/operations/op-12-refresh-tokens.md) (`SAIF.NetCore.OIDC`); `LowerCaseUrlMiddleware`'s logic is in [`Enforce URL casing`](../../saif-netcore-oidc/operations/op-13-enforce-url-casing.md).
6. `UseHsts()` always runs; if `EnforceSslRedirect`: `UseHttpsRedirection()` ([BR-SE-19](../business-rules.md#br-se-19-hsts-is-always-on%3B-https-redirect-is-configurable-for-web-apps))
7. `UseStaticFiles()`, `UseRouting()`, `ConfigureAuthorization()` (virtual method, default implementation calls `UseAuthorization()`), `ConfigureUI()` (abstract — implemented by `OidcMvcStartup`/`OidcRazorStartup`, see [OIDC MVC and Razor startup](oidc-mvc-and-razor-startup.md)), then `ConfigureSaifLogger()` (`IAppBuilderExtensions.cs`), which resolves `ISaifLogService`, `IEnvironmentClient`, `IHttpJsonClient`, and `IHttpContextAccessor` from `app.ApplicationServices` and calls `loggingService.Configure(environmentClient, apiLogClient, contextAccessor)` synchronously, as the final step of `Configure`.

   > **Origin**: `loggingService.Configure(...)` resolves to `SaifLog.Configure` (`SAIF.NetCore.Logging`), whose own setup/override/correlation-ID machinery is documented in full on [`OP-01: Configure the web logger (SaifLog)`](../../saif-netcore-logging/operations/op-01-configure-web-logger.md) and executed synchronously on behalf of this step. In outline: it resolves the base log threshold from the Environment API (falling back to `tracingdefaults:logthreshold`), builds the standard `ApiLoggerConfig`/`EventLogConfig` sink configurations and applies any `SaifLogging:BaseLevel`/`SaifLogging:Loggers` `appsettings.json` overrides, sets `ExFormatService` to a new `ExceptionFormatServiceForWeb(environmentClient, httpContext)` (the web-specific exception formatter this step's `IHttpContextAccessor` argument feeds), calls `Log.CloseAndFlush()` to close out any prior logger, reads `tracingdefaults:loggingapiurl`/`logroute`/`logerrorroute` from the Environment API and pushes them into the injected `IHttpJsonClient`, builds the Serilog logger (Event Log sink, `LoggingApiSink`, Console sink), and finally sets `IsConfigured = true` so subsequent log calls are accepted. The type-level reference is [`SaifLog`](../../saif-netcore-logging/api/SAIF.NetCore.Logging/SaifLog.md) (`SAIF.NetCore.Logging`).

## Process flow

This diagram shows the request-pipeline assembly performed once, synchronously, by `Configure` during host startup — not per-request middleware execution order beyond what each `Use*` call wires in.

```mermaid
flowchart TD
    Start([Configure invoked]) --> S1[Enable request buffering]
    S1 --> S2{EnableSessionMiddleware?}
    S2 -->|Yes| S2a["UseSession + AspNetSessionIdMiddleware"]
    S2 -->|No| S3["ConfigureErrorHandling + ConfigureDebugRequestHandling"]
    S2a --> S3
    S3 --> S4[UseAuthentication]
    S4 --> S5{HostLocation == External?}
    S5 -->|Yes| S5b{AuthenticationChallengeType == OpenIdConnect?}
    S5b -->|Yes| S5c[LowerCaseUrlMiddleware]
    S5b -->|No| S5a["JwtClaimMiddleware (always)"]
    S5c --> S5a
    S5a --> S5d{UseJwtRefreshMiddleware?}
    S5d -->|Yes| S5e[RefreshJwtMiddleware]
    S5d -->|No| S6[UseHsts]
    S5e --> S6
    S5 -->|No| S6
    S6 --> S7{EnforceSslRedirect?}
    S7 -->|Yes| S7a[UseHttpsRedirection]
    S7 -->|No| S8["UseStaticFiles / UseRouting / ConfigureAuthorization /<br>ConfigureUI"]
    S7a --> S8
    S8 --> S9["ConfigureSaifLogger resolves services<br>and configures ISaifLogService"]
    S9 --> EndOk([Pipeline fully composed])
```

## Failure and edge-case behavior
- `ConfigureAuthorization` is virtual, so a derived Startup class can replace the default `UseAuthorization()` call.
- `ConfigureUI` is abstract and must be implemented by the concrete Startup type ([OIDC MVC and Razor startup](oidc-mvc-and-razor-startup.md)).

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `src/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/SAIF.NetCore.ServiceExtensions/Startup/AppStartup.cs`
