reverse-proxy icon indicating copy to clipboard operation
reverse-proxy copied to clipboard

Request "/foo/" incorrectly matches to Ingress rule with Exact Path "/foo"

Open specialforest opened this issue 2 months ago • 1 comments

Describe the bug

@miaxzhitong found an issue when Ingress rule with Exact Path "/foo" matches a request "/foo/" (and the other way around too). Per https://kubernetes.io/docs/concepts/services-networking/ingress/#examples it should not match:

Kind Path(s) Request path(s) Matches?
Exact /foo /foo/ No
Exact /foo/ /foo No

specialforest avatar Oct 01 '25 21:10 specialforest

YARP inherits this behavior from ASP.NET Core's routing. Note that if you define routes that only differ by the trailing slash, requests will match both (and fail).

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/foo", (HttpRequest request) => $"Foo - {request.Path}");
app.MapGet("/bar/", (HttpRequest request) => $"Bar - {request.Path}");
app.MapGet("/baz", () => "Baz");
app.MapGet("/baz/", () => "Baz/");

const string Url = "http://localhost:5000";

_ = Task.Run(async () =>
{
    using var client = new HttpClient();

    Console.WriteLine(await client.GetStringAsync($"{Url}/foo"));         // Matches foo
    Console.WriteLine(await client.GetStringAsync($"{Url}/foo/"));        // Matches foo
    Console.WriteLine(await client.GetStringAsync($"{Url}/bar"));         // Matches bar/
    Console.WriteLine(await client.GetStringAsync($"{Url}/bar/"));        // Matches bar/
    Console.WriteLine((await client.GetAsync($"{Url}/baz")).StatusCode);  // Ambiguous (500)
    Console.WriteLine((await client.GetAsync($"{Url}/baz/")).StatusCode); // Ambiguous (500)
});

app.Run(Url);

Is this causing you problems in practice?

MihaZupan avatar Oct 01 '25 22:10 MihaZupan