Draft
Conversation
Routes-first design for the YARP container app's static-host pipeline: - Redirects -> Map(...).ShortCircuit() routed endpoints (early order). - NavigationFallback.Exclude -> MapFallback(...) endpoints ordered just ahead of the SPA fallback so proxy and other real routes still win. - Headers -> middleware that targets static-file responses (OnPrepareResponse) and the SPA fallback (OnStarting via endpoint metadata). Static files are not endpoints, so this remains the only consumer of RequestMatchEvaluator.TryMatch. - StaticFilesFeature wraps UseFileServer to stash/clear and restore the selected endpoint, preserving the rule that static files beat routed fallback endpoints while routed real endpoints still win. - RequestMatchEvaluator exposes a static ValidatePath helper so callers that delegate matching to ASP.NET routing skip the TemplateMatcher allocation entirely. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Delegates to the standard ASP.NET rewrite middleware
(Microsoft.AspNetCore.Rewrite) instead of inventing a new syntax.
Config maps directly to RewriteOptions.AddRewrite parameters:
{ "Regex": "^old/(.*)$", "Replacement": "new/$1" }
Slots in before UseRouting so every downstream stage (route matching,
static files, redirects, SPA fallback, reverse proxy) sees the
rewritten path. SkipRemainingRules defaults to true (first match wins);
set false to chain rewrites.
7 new tests cover passthrough, capture-group substitution, ordering vs.
routing/redirects/proxy/fallback exclusions, and the no-chaining
default.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- RedirectsFeature and NavigationFallbackExclusionsFeature captured the loop variable 'i' in the .Add() callback. Endpoint convention callbacks run after the loop completes, so all endpoints were getting the same final Order value. Hoist Order into a per-iteration local. Existing tests didn't catch this because each rule has a unique path, so Order ties weren't observable. - Wrap RewriteOptions.AddRewrite in try/catch so an invalid Regex pattern surfaces as 'Rewrite rule at index N has an invalid Regex pattern "..."' instead of a generic ArgumentException from the Regex constructor. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Adds a 'Request pipeline' section to the application README that lays out the eight stages (rewrites -> routing match -> redirects -> static files -> headers -> reverse proxy -> fallback exclusions -> SPA fallback) as the central mental model, plus a 'Match syntax' note explaining why routed features use route templates while Rewrites use regex (delegation to the standard rewrite middleware). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Maps HTTP status codes to custom response files via re-execute. Supports
exact codes ("404") and class wildcards ("5xx"); exact wins over wildcard.
Slots between Rewrites and Routing in the request pipeline.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Clear the response before re-executing a configured error page so routed and proxied targets can run normally, then restore the original status code before the response is sent. Add coverage for a proxied error page target that writes 200 OK while the client still receives the original 404. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add five realistic config/static-file sample apps that demonstrate the YARP application static-hosting and routing-rule features: marketing site headers, docs redirects/rewrites, dashboard API proxying, custom commerce error pages, and a composed edge frontend. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Normalize table spacing and remove an extra trailing blank line so markdownlint passes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The previous Azure Ubuntu leg failed in ReverseProxy.FunctionalTests Expect100Continue coverage, unrelated to the YARP Application changes in this branch. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add comments explaining why custom error pages clear response state, restore the original status code, and reset routing state during re-execute. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Document the route-template, rewrite regex, redirect destination, and error-page key parsing paths with concrete examples so the config syntax is easier to follow in code. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move relative endpoint order values to named constants and explain how endpoint routing uses those ranges for redirects and SPA fallback exclusions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds routing-rule features to the YARP application static-hosting experience so the pre-built app can cover common static site, SPA, edge frontend, and simple reverse-proxy composition scenarios without writing code.
This includes:
Headers[]for static-host responsesRedirects[]as routed short-circuit endpointsNavigationFallback.Exclude[]for paths that should not fall back to the SPA shellRewrites[]using the ASP.NET Core rewrite middleware syntaxErrorPagesfor custom exact-code andNxxwildcard error pagessamples/YarpApplication.SampleAppsMental model
The app is composed as a small request pipeline. Each feature has a clear position and responsibility:
Important consequences:
Matching model
There are two intentional matching syntaxes.
Routed features use ASP.NET route templates
This applies to:
Headers[].Match.PathRedirects[].Match.PathNavigationFallback.Exclude[].PathExamples:
{ "Path": "/api/{**catch-all}" } { "Path": "/docs/{slug}" }Redirects[].Destinationcan reference route values captured from the match:{ "Match": { "Path": "/docs/{**slug}" }, "Destination": "/articles/{slug}", "StatusCode": 301 }Rewrites use ASP.NET Core rewrite middleware syntax
No new rewrite DSL is invented. Rewrites use regex + replacement capture groups:
{ "Regex": "^legacy/(.*)$", "Replacement": "api/$1" }SkipRemainingRulesdefaults totrue, matching “first rewrite wins” behavior.Error pages
ErrorPagesmaps status codes to custom pages:{ "ErrorPages": { "404": "/errors/not-found.html", "5xx": "/errors/server-error.html" } }Rules support:
"404","503""4xx","5xx"The implementation re-executes the request against the configured page, clears/resets response state so routed/proxied targets can run, and preserves the original HTTP status code before the response is sent.
Samples
Adds five config/static-file sample apps:
01-marketing-site02-docs-site03-dashboard-spa/apiproxy exclusion04-commerce-errors05-edge-compositionThese are intentionally not .NET apps; they are realistic
appsettings.json+wwwrootlayouts for the YARP application.Validation
dotnet test test/Application.Tests/Yarp.Application.Tests.csproj