Comments (12)
I've migrated the entire PR into its own repository a while ago. It builds and I think it should work now, but might need a bit of testing with the latest version of Giraffe. I also have to set up the build pipeline for a NuGet package, which I should be able to get done over the next few days:
https://github.com/giraffe-fsharp/Giraffe.Swagger
If you have any questions or want to help then please open a new issue there.
from giraffe.
@dustinmoris, the big argument for automatic doc generation is safety and maintenance. It's no different from how Project Scaffold autogenerates an API reference page, as countless other documentation tools have done since Javadoc.
Would you want to write those by hand, having to constantly keep them up-to-date and potentially committing all kinds of human errors? If not, why is it different when it's an HTTP request rather than a library function call?
Also if I'd be working in a team which has to document an API with Swagger, then I wouldn't want to tie the Swagger generation to .NET code, because now only .NET developers can generate or update the documentation. On the other hand a .yml file is supposed to be human friendly for reading, understanding and editing, so in theory I could pass on the documentation to a stakeholder, QA person, product owner, or anyone else on a team who could test the API according to the .yml file and potentially correct any issues in the .yml file themselves. This is sort of one of the big benefits of Swagger and by moving the doc generation to .NET code this whole purpose gets lost, right?
Eh, not really. First, Swagger/OpenAPI is meant at least as much for machines as for humans - the documentation it generates is a reference, not a presentation. Sure, you can write it by hand in YAML, and read the YAML with human eyes, but that's a plan B compared to using swagger-codegen
and similar tools (although an important plan B: it mitigates the WSDL scenario where it's awesome if your IDE automagically integrates it and horrible if it doesn't).
If you have the luxury of tasking a non-developer with writing proper documentation, then Swagger isn't likely to be their tool of choice, because (a) it's very restricted (nothing but plaintext or at best Markdown descriptions, forget about pictures and diagrams), and (b) a basic reference layout makes for poor learning. It's no coincidence that the spec includes an external-docs
URL field for most objects.
If you don't have the luxury of writing proper documentation - that's where Swagger and similar tools come in. Just comment your public API calls and your objects' public properties and you'll have at least a usable reference, if nothing else. Or even if you don't comment it at all, the tooling will still create a reference of your method signatures.
In any case, putting my money where my mouth is: I've been working on an OpenAPI (Swagger 3.0) library for Suave, still using a wrapper-based approach but with what I hope is going to be a much less clunky UX than the existing Suave.Swagger module (basically I'm providing most of the same combinators as Suave, choose
, GET
, Ok
/NotFound
etc., except these combinators are records containing both a WebPart
and a DocPart
, the latter of which combine to create the spec).
Once I publish it, it should be quite straightforward to port it from WebPart
to HttpHandler
, since the structure is so similar. That said, if Giraffe could support APIExplorer
and then lean onto Swashbuckle's more well-established tooling and user base, that would be a much more robust solution (and more in line, I think, with Giraffe's philosophy of 'let's use the big boys' stuff').
from giraffe.
https://github.com/Microsoft/OpenAPI.NET
from giraffe.
Hi, could anyone review PR #218, please? This nasty feature ready, I hope, to satisfy all its possible consumers!
Ci is failed due to 'dotnet-xunit' not found, perhaps you forget to add NuGet package .
from giraffe.
I was thinking about this a few months ago, I found it an interesting thought experiment.
Giraffe doesn't directly use MVC (well it does for the Razor engine), it uses ASP.NET Core directly, so Swashbuckle
/ApiExplorer
isn't something we get for free, so I think the question is how do we expose a swagger doc for a Giraffe composed app in an easy and idiomatic way.
In terms of web frameworks, approaches vary vastly, for example:
ASP.NET MVC - This is convention based, and you can deviate from the conventions, at runtime you can reflect on the current application. You can enumerate the routes, then reflect on the controllers. Where the types are exposed (cause IHttpActionResult
is not generic) you can influence the swagger docs with attributes.
Freya - You compose an application that results in a decision tree, at runtime this is reduced, optimized and executed, which is pretty cool. It also means that this tree can be walked through and swagger docs can be built from the collected information provided by this tree, very cool.
Suave & Giraffe - These frameworks let you build you app as just a function, with functional composition. This makes things simple, and fast. That said, the above frameworks are fast too, but they require hard work and complexity inside the framework code to achieve this, Giraffa gets it for free =)
Because it is just a function, you can only invoke it, so you could pass in a dummy request through it and capture the output, but you don't know how to vary the request to explore the whole app and reverse engineer it. What you would need is to be able to pass through a collector, each HttpHandler
(or Suaves WebPart
) would contribute to it, and the combinators would know to always continue and pass it through.
@piaste I hadn't considered the approach you had highlighted above where you provide a separate dsl that mirrors the original, and under the hood builds you the "plan" dsl version, and builds the swagger. And to do it by utilizing ApiDescription
is also an interested suggestion, I'd be interested in just hacking about and seeing if this was possible, although don't realistically have the time. Would love to hear other thoughts on this.
from giraffe.
Gentlemen, this may be something we can build in as default on new routing system as the base function becomes a radix tree with route endpoint handlers such that all routes should be easily iterated through so that each route can be tested/mapped. May mean two versions of the router (or base function has a parameter to expose swagger or not). We can do a bit of hacking once router released.
One thing to note is that api parse variables are largely printf
format of %s
%i
etc, such that they are not named which makes the api less expressive. We would need to either change the parser to use named variables or add annotations/metadata.
Adding named variables is not as easy as it sounds without adding more work for the dev (StringFormat<'T> generates type sig from string), I had been prototyping generative type-provider to allow the parsing & creation of types based on a named parameter api string but generative type providers do not work on .net core yet (and erased are not performant enough for high throughput routing), so it forces the user to define named property types for each and every route parse which is a pain when StringFormat/printf can magically create the type for you.
from giraffe.
I wonder how good these auto generation tools really are, because how do these tools document error responses which often come from a central module or error handler or how do these tools document endpoints across different middleware?
from giraffe.
@dustinmoris I think for the basic documentation case (Swagger has extensive functionality), swagger would just list the api endpoint URLs and in a method similar to postman/fiddler, you can test urls with variables etc on a live server so that you can see the response (or error response). On diff middleware...need to explicitly do mapping? Would question effort alright. Looking further into it more problems stack up
- As mentioned already, currently parse symbols are not named
- Much of the value is in comments/description of api so we would need annotations on all routes ... but annotations are not allowed on specific instances of a common class so needs to be a function param.
- handling of Authentication, Verbs etc all needed but again class/method annotations not viable
That being said, it is probably appealing to some so as a separate nuget package it may be nice provided it does not pollute the base Giraffe library.
The likely solution would be different handler namespace that replaced certain handlers with wrapped/overloaded versions that interacted with an internal state object (held in HttpContext Items Dictionary) such that it could iterate it on build/startup and generate the swagger spec json file that could then be viewed through the online swagger viewer.
There would need to be some pretty good interest to go through all this design & coding IMHO ... if you look at the Suave implementation example, yes it works but I would find it a nightmare to program, adding so much clutter and complexity vs standard api of an app.
from giraffe.
Hi,
This issue has been a little bit stale and I do not only wonder how realisitc it is to get this done, but also if it is really any useful.
I still struggle to understand the actual value of this, because I don't think there's any less work for a developer after all. Instead of having to document an API in yml the user now has to document the API with .NET attributes (or some other F# construct).
So basically it is still up to the developer to
a) document the API manually
b) not forget to update attributes or something else when the API changes
Seems to me that this is a lot of work for merely shifting documentation from YML to .NET code, without a clear benefit. Now the one thing which I really struggle to understand is: Swagger is supposed to be a user friendly and easy way of documenting APIs. Unlike .NET or F# it has been specifically designed for that one purpose only, so how can .NET attributes be superior in documenting an API than a language/tech which has been specifically designed for it? If Swagger is still too complex, then should the people who want to document APIs not rather look for improvements of Swagger instead?
Also if I'd be working in a team which has to document an API with Swagger, then I wouldn't want to tie the Swagger generation to .NET code, because now only .NET developers can generate or update the documentation. On the other hand a .yml file is supposed to be human friendly for reading, understanding and editing, so in theory I could pass on the documentation to a stakeholder, QA person, product owner, or anyone else on a team who could test the API according to the .yml file and potentially correct any issues in the .yml file themselves. This is sort of one of the big benefits of Swagger and by moving the doc generation to .NET code this whole purpose gets lost, right?
from giraffe.
Instead of having to document an API in yml the user now has to document the API with .NET attributes (or some other F# construct).
With ASP.NET Core API Explorer this happens almost automatically.
You don't use any attributes additional to ASP.NET Core except for sample view models.
So why not just plug Giraffe into API Explorer?
For me I don't understand a benefit of having a single route composition root like Giraffe obligates to do. I would better decorate functions with attributes and never mind of fixing routes decision tree.
from giraffe.
We use Swagger extensively at work for things like:
- PO checking input/output on a new feature
- Documentation of the APIs
- Auto-generation of clients for the APIs for various programming languages
It definitely beats maintaining a yaml file (which I have done in the past) for both creation and staying up to date.
Not having this would unfortunately make Giraffe a non-starter in an environment where is is expected.
A few ideas have been mentioned, does anybody have a good feel for how to move forward on this?
from giraffe.
Hi,
I did not find solution to populate ApiDescription.
But I explored another solution in this PR #218
Regards,
from giraffe.
Related Issues (20)
- Migrate to System.Text.Json HOT 1
- Participate on hacktoberfest 2023? HOT 1
- Never decalre reader with `use` on `ctx.Request.Body` HOT 4
- Upgrade to .NET 8 HOT 6
- LinkGenerator doesn't work with routef HOT 1
- Giraffe 6.2 is breaks against Microsoft.IO.RecyclableMemoryStream 3.0.0 HOT 11
- Returning streams, either with WriteStreamAsync or WriteFileStreamAsync or their handler equivalents, is extremely slow HOT 4
- Question: How to approach outside in testing of a micro service? HOT 2
- Guid pattern in endpoint router matches invalid values, throws System.FormatException HOT 6
- Follow-up from "Minor code optimisation #567"
- Update SECURITY.md
- Start using fantomas to validate code submissions with CI HOT 6
- [README] Suggestion for "Getting Started"'s "Doing it manually" HOT 2
- [question] Would it be possible to make `Giraffe.EndpointRouting` case-sensitive? HOT 3
- Remove NuGet API key from the repository HOT 3
- 6.4.0 release references PR for updating to .NET 7 instead of .NET 8 HOT 1
- EndpointRouting - Create endpoint for multiple http verbs
- Request/discussion: WriteStreamAsync buffer size autotuning and/or increase default buffer size HOT 1
- Update `.vscode` debug configuration to point to existent projects
- Returning 406 when mustAccept fails HOT 8
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from giraffe.