Giraffe icon indicating copy to clipboard operation
Giraffe copied to clipboard

LinkGenerator doesn't work with routef

Open marcingolenia opened this issue 2 years ago • 1 comments

Hi there, I tried different ways but I just can't get the LinkGenerator to work with routef. Let's say I have this endpoints:

let endpoints =
    [
        GET [
            route "/houses" readHauses |> addMetadata(EndpointNameMetadata "get_houses")
            routef "/houses/%s" readHauseBy |> addMetadata(EndpointNameMetadata "get_house")
        ]
    ]

and this 2 handlers:

let readHauses: HttpHandler =
    fun (next : HttpFunc) (ctx : HttpContext) ->
        let linkGenerator = ctx.GetService<LinkGenerator>()
        let data = houses |> List.map(fun house ->
            { Name = house
              Links = [{ Rel = "self"
                         Href = linkGenerator.GetUriByName(ctx, "get_houses")
                         Method = "GET" }]
            })
        json data next ctx

let readHauseBy (name: string): HttpHandler =
    fun (next : HttpFunc) (ctx : HttpContext) ->
        let arr = new ResizeArray<string>()
        arr.Add("Gryffindor")
        let linkGenerator = ctx.GetService<LinkGenerator>()
        let link2 = linkGenerator.GetUriByName(ctx, "get_house", "name", "teest")
        let link1 = linkGenerator.GetUriByName(ctx, "get_house",  arr)
        let link3 = linkGenerator.GetUriByName(ctx, "get_house")
        let link3 = linkGenerator.GetUriByName(ctx, "get_house")
        json {| Name = name; Capacity = 200 |} next ctx

In the first handler I am able to get the Uri by name. In the second... well.. no way. Ideas? In C# we can use it like this:

app.MapGet("/houses/{id}", (int id) =>
{
    return Results.Ok();
})
.WithMetadata(new EndpointNameMetadata("get_product"));

but here I have "{id} in the string, not "%s" I guess this might cause some issues. Any hints?

marcingolenia avatar Dec 08 '23 22:12 marcingolenia

Ok, I know now that the format string is translated to route template like so; linker_giraffe

So getting the path works: linker.GetPathByName("get_houses_by", {|s0 = "test"|})

Now I am wondering if

  1. Giraffe (optionally) could work with ekhm.... route templated format strings? :D Like so; routef "/houses/%s{Name}" readHauseBy |> addMetadata(EndpointNameMetadata "get_house") ?
  2. Or if the route template names can be somehow inferred from handlers? let readHauseBy (name: string): HttpHandler =
  3. Or if the routeBind handler can be made to work with new EndpointRouting? (I guess that one will work better with LinkGenerator).

Ideas? Suggestions? I even my try to submit a PR with something but I want to go through discussion which way would be the best here.

marcingolenia avatar Jan 20 '24 21:01 marcingolenia