Giraffe.TokenRouter icon indicating copy to clipboard operation
Giraffe.TokenRouter copied to clipboard

Routing - no result on similar routes with first letter collision

Open alexswan10k opened this issue 5 years ago • 0 comments

I have unfortunately hit a rather subtle bug around similar routes and I am having trouble getting to the bottom of the route cause (there is quite a lot going on in the underlying algorithm that might make more sense to someone who knows the codebase). I am happy to dig in further but I may need a little help!

I have written a failing test that demonstrates the scenario:


[<Fact>]
let ``GET Similar routes should correctly resolve`` () =
    let ctx = Substitute.For<HttpContext>()
    let app =
        router notFound [
            GET [
                routef "/api/%s" (fun _ -> text "a")
                route "/api/csv" (text "b")
            ]
        ]

    ctx.Request.Method.ReturnsForAnyArgs "GET" |> ignore
    ctx.Request.Path.ReturnsForAnyArgs (PathString("/api/cat")) |> ignore
    ctx.Response.Body <- new MemoryStream()
    let expected = "a"

    task {
        let! result = app next ctx
        match result with
        | None     -> assertFailf "Result was expected to be %s" expected
        | Some ctx -> Assert.Equal(expected, getBody ctx, true)
    }

It looks like it is the first character of route segment that seems to be the issue here. If the first char is the same, it seems to bypass both routes and return NotFound. If I change either the positional parameter to "bat" for example, the example works.

In more complex scenarios this is leading to all sorts of problems. In my real app i have various routes like /api/guid/whatever, which seem to be spontaneously failing when using specific GUID's, which I have now discovered is because I have fixed routes of /api/{prefix}..../ which are colliding.

Please let me know where is best to go from here - I am happy to submit a PR with the failing test etc.

alexswan10k avatar Jan 16 '20 16:01 alexswan10k