Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swagger supports normal minimal asp.net core apis but not work for Giraffe endpoints #488

Open
albertwoo opened this issue Jul 15, 2021 · 16 comments

Comments

@albertwoo
Copy link

I am playing around with asp.net core 6.0.100-preview.6.21355.2
I found the swagger works for default endpoint routes like in below code the /hello2 will be picked by swagger, but not work with giraffe endpoints.

open System
open Microsoft.AspNetCore.Http
open Microsoft.AspNetCore.Builder
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.DependencyInjection
open Giraffe
open Giraffe.EndpointRouting

let builder = WebApplication.CreateBuilder()

builder.Services.AddEndpointsApiExplorer()
builder.Services.AddHttpContextAccessor() |> ignore
builder.Services.AddSwaggerGen() |> ignore

let application = builder.Build()

application.UseSwagger() |> ignore
application.MapGiraffeEndpoints
    [
        GET [
            route "/hello1" (text "Hello")
        ]
    ]
application.MapGet("/hello2", Func<_, _>(fun (ctx: HttpContext) -> $"Hi {ctx.Request.Path}")) |> ignore
application.UseSwaggerUI() |> ignore

application.Run()
@albertwoo
Copy link
Author

This root reason should be similar with falco:
pimbrouwers/Falco#49

@Numpsy
Copy link

Numpsy commented Jul 21, 2021

This was mentioned in the talk at https://www.twitch.tv/videos/1092464368 yesterday (right at the end, and in relation to https://github.com/baronfel/Giraffe.EndpointRouting.OpenAPI I think).
It sounds from that like the requirements for the new MS stuff to work on its own are quite specific (I haven't tried using the new v6 stuff myself yet though)

@baronfel
Copy link
Contributor

baronfel commented Jul 21, 2021

Yep I brought it up on purpose because I'd seen this discussion pop up again (and also I'm the Falco repo).

The relevant code in aspnetcore is here, the gist of which is to translate specifically minimal endpoints that are described by lambdas (or method groups) by their endpoint Metadata (which includes the reflection Method info) into ApiDescriptors.

This doesn't work for giraffe at all because composed endpoints don't match this pattern, so if we want to interop at the level that Swashbuckle does, we'd need to implement our own Apidescriptor provider that could create these same structures from giraffe apis. Swashbuckle would then be able to take our ApiDescription and generate the swagger doc from that.

That's where the fiddly work comes in, as far as I can see it.

Link to the brief video clip where I go over this is here

@jkone27
Copy link

jkone27 commented Dec 23, 2021

this project was archived but could be helpful, at least for the openapi CE writer part?
https://github.com/akhansari/FSharp.OpenApi

@jkone27
Copy link

jkone27 commented Jan 14, 2022

dotnet/aspnetcore#37098

@jkone27
Copy link

jkone27 commented Jun 24, 2022

maybe something new can be tried with these updates on openapi and metadata?

https://devblogs.microsoft.com/dotnet/asp-net-core-updates-in-dotnet-7-preview-4/

@voronoipotato
Copy link

This would be really helpful for companies that are reliant on openapi and swagger. @baronfel thanks for the work to describe this.

@captainsafia
Copy link

Coming across this issue from domaindrivendev/Swashbuckle.AspNetCore#2300.

This doesn't work for giraffe at all because composed endpoints don't match this pattern, so if we want to interop at the level that Swashbuckle does, we'd need to implement our own Apidescriptor provider that could create these same structures from giraffe apis. Swashbuckle would then be able to take our ApiDescription and generate the swagger doc from that.

@baronfel's recommendation here is exactly right. Providing a custom IApiDescriptionProvider interface is the pathway that frameworks should take in order to light up support for OpenAPI in ASP.NET Core. The IApiDescriptionProvider is essentially the middleman introspection layer that allows other tooling (like Swashbuckle, NSwag, or the new built-in OpenAPI support coming in .NET 9) to determine what metadata it should generate.

The link above points to minimal API's implementation (see here). There's also implementations for MVC (see here) and gRPC (see here) that can be used as examples.

@voronoipotato
Copy link

@captainsafia thank you so much for helping provide tangible examples. maybe one day if I can find the time I'll try and mess around with an implementation attempt. Having swagger for Giraffe would really help unify our C# and F# api descriptions.

@64J0
Copy link
Member

64J0 commented Jul 17, 2024

Apparently it was fixed by PR #599. What you think?

@64J0 64J0 added the waiting response waiting for more info from the OP label Jul 17, 2024
@captainsafia
Copy link

Apparently it was fixed by PR #599. What you think?

One thing about this approach I spotted is that it makes use of the WithOpenApi extension method to opt-in to the OpenAPI generation done by this bit of code. One thing to note about this pattern is that it only works with Swashbuckle and there's no plans to support it in the new Microsoft.AspNetCore.OpenApi package. See domaindrivendev/Swashbuckle.AspNetCore#2849.

One thing I'm observing about your implementation though: do the endpoints generated by Giraffe eventually get populated into the EndpointDataSource? If so, then the built-in IApiDescriptionProvider implementation for endpoints (see here) should be able to pick them up and you'll be able to light-up OpenAPI support without taking a dependency on a singular package (since they all use ApiDescription's as the source of truth).

@NinoFloris
Copy link
Member

It's likely that they're added as RequestDelegates instead of taking the Delegate overload. Only the latter will populate the MethodInfo required to make them flow through automatically through the built-in IApiDescriptionProvider. Ran into exactly this recently while fixing a closed source 'giraffe light' implementation. F# doesn't have the automatic coercion from lambdas (FSharpFunc) to Delegate like C# introduced in 10.0 which meant explicit RequestDelegate construction spread all over the F# ecosystem, even when it was the only endpoint type.

@64J0 64J0 removed the waiting response waiting for more info from the OP label Jul 19, 2024
@jkone27
Copy link

jkone27 commented Oct 15, 2024

Maybe related for reference

@mrtz-j
Copy link
Contributor

mrtz-j commented Oct 22, 2024

Maybe related for reference

* [openapi not working (tried both builder and slimbuilder) Lanayx/Oxpecker#25](https://github.com/Lanayx/Oxpecker/issues/25)

* https://github.com/pimbrouwers/Falco/tree/develop/src/Falco.OpenApi

I've a working sample app here. It uses the Giraffe.OpenApi package.

@voronoipotato
Copy link

Does anything need to get merged or is this currently working?

@captainsafia
Copy link

Does anything need to get merged or is this currently working?

I think this currently works with the caveat that it uses the soon-to-be-deprecated-ish WithOpenApi extension method in ASP.NET Core which is currently only designed to work with Swashbuckle (see #488 (comment)). If you're OK with that constraint, then you can probably consider this resolved with the implementation in the package referenced above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants