rwf2 / Rocket

A web framework for Rust.
https://rocket.rs
Other
24.51k stars 1.57k forks source link

[Feature Request] Rocket auto-documentation route #297

Open TheDan64 opened 7 years ago

TheDan64 commented 7 years ago

Hi, thanks for all your hard work. Rocket is awesome!

I think it would be an absolute killer feature if route/endpoint API documentation could somehow be generated right from Rocket. For example, in Python, Sphinx has the capability to pull routes' docstrings right from the endpoints and build HTML document(s) that get mounted to /docs and formats the docstrings via rst templates(for added customization). However, these docstrings are managed by the developers, so I'm wondering if there's the possibility for generating all (or almost all - maybe allowing for additional comments or descriptions of failure cases, etc) of the information straight from Rocket types.

So I guess I'm imagining something like rustdoc, where the primary difference is a focus on routes rather than rust methods. So for example, the Rocket route:

/// This endpoint gets a user by their id
#[get("/user/<id>?<bar>")]
fn get_user(id: u64, bar: Option<String>) -> JSON {
    ...
}

Could be auto documented to something like the following, though prettier in HTML&CSS:

GET /user/<id>?<bar> -> JSON<User>
Path variables:
    id: int

Params:
    bar: string (optional)

This endpoint gets a user by their id

And maybe User could link to a definitions page/or have a hover display type of thing for reference:

User: {
    id: int,
    name: string,
}

I'm thinking enabling the autodoc would be easy to set up:

rocket::ignite().mount("/", routes![get_user]).docs("/docs").launch();

Or with a more rocket-themed name! (ground_control?!)


So, to respond to the required information more directly:

I think this feature is necessary because it would be a huge boon to developers. One team could quickly mock up a couple endpoint and data model (ie User) definitions and then point other consuming team(s) to their documentation almost immediately.

I suppose this feature could exist outside of rocket as some sort of plugin, but I think auto documentation would be a common use case so it might make sense for it to be easily accessible right away when developing a Rocket app.

corbinu commented 7 years ago

I think this is a great idea but this would be better served as a plugin. For example I want to have the API documented as swagger, but others might want another format.

Currently in my node projects I use this: https://github.com/glennjones/hapi-swagger which I think is a great example of how this can be done super well.

bluejekyll commented 7 years ago

FYI: I just played around with generating a quick Swagger/OpenAPI Spec: https://users.rust-lang.org/t/anyone-working-on-swagger-openapi-support-in-rocket/11231

But something like what is being suggested here would greatly help in generating these docs. There's a lot more information desired, like types from the function parameters. A generator is probably the correct thing...


Update: I started a library for rocket-openapi integration: https://github.com/bluejekyll/rocket-openapi It relies on this PR: #326 for some additional details about the endpoints. It would be great to get some feedback on this.

TheDan64 commented 7 years ago

OpenAPI support is definitely a good idea! Looking forward to seeing how that goes.

I guess my idea was leaning towards it being its own documentation endpoint because I got the feeling that Rocket has a much richer source of type information than can be leveraged by existing docs/standards like swagger/openapi alone.

bluejekyll commented 7 years ago

I am deriving the OpenAPI docs directly from the Rocket Route, etc. I plan to get the type information as well for all params and return types. We'll see if that's information that people will want in Rocket itself, of if we'll need a separate crate for generating that.

I would be surprised if we can't support all potential documentation options in OpenAPI, but also I see it as extremely important, as that's a great way for auto-generating client libraries for other languages.

Right now this basically looks like this:

let lit = rocket::ignite().mount("/app", routes![test_endpoints::hello_param]);
let spec = rocket_openapi::build_swagger_spec(&lit, "Hello World", "1.0");
lit.manage(spec).mount("/openapi", routes![rocket_openapi::spec]).launch();
pickfire commented 6 years ago

What about api documentation with rustdoc (since rocket already generate some doc)?

vadixidav commented 6 years ago

What's the status on this? This is very important for running in enterprise. I would like to use Rocket at work and have documentation generated this way.

SergioBenitez commented 6 years ago

@vadixidav As far as I know, there hasn't been progress on this beyond what @bluejekyll posted. I'd be happy to mentor someone on an implementation of this feature.

DJMcNab commented 6 years ago

When I have more time, I was planning on making something similar for actix/actix-web (#310). I'm sure that I could use at least some of the work for that to implement this.

vultix commented 5 years ago

@SergioBenitez I'm interested in taking this on if you're willing to help mentor.

GREsau commented 5 years ago

I've been spending some time on this over the past few weeks and I've managed to get something that works for very simple scenarios (https://github.com/GREsau/okapi). You can't really generate useful Swagger without also generating JSON Schema for the request/response types, so I also had to make a JSON Schema generator (https://github.com/GREsau/schemars).

In order to generate the correct schemas I needed access to the parameter types and return types of route functions. Since I'm not aware of any way I could feasibly get them from Rocket's APIs, I unfortunately had to make my macros re-parse the route attributes that Rocket uses.

All it really requires is that any structs used as route parameters/responses derive JsonSchema, and then using the routes_with_openapi! macro instead of Rocket's routes!, which will add a route at openapi.json which returns to generated spec. There's also a helper to set up Swagger UI.

It's all a very early-on/hacky/untested/undocumented right now, but I've got a demo running at: https://7wuxfncqt2.execute-api.eu-west-1.amazonaws.com/Prod/swagger-ui (Swagger UI) https://7wuxfncqt2.execute-api.eu-west-1.amazonaws.com/Prod/openapi.json (raw OpenAPI JSON)

The source code for that demo is at https://github.com/GREsau/okapi/blob/master/examples/json-web-api/src/main.rs

kdy1 commented 3 years ago

I made https://github.com/kdy1/rweb which uses scoped thread local (https://github.com/kdy1/rweb/blob/2e96a95d6593d781faa6e6070d08547f14e33c21/src/openapi/mod.rs#L226) while registering routes. I think this can be applied to rocket even if routes are mounted using non-root path.

Note: This can't be used to create openapi spec during compilation, which is impossible because of various things like mount path. But you can create a specification file and terminate based on the command line arguments or environment variables. (I'm doing so at the moment)

Will you accept such PR?

I don't want to waste time, so I want to know if it'll be merged before sending a PR.

chriskuech commented 3 years ago

I am starting a new project soon and I'm really hoping to use Rocket, but OpenAPI support is a determining feature. I've looked at okapi but code genning off Rocket inherently requires tight coupling to Rocket which causes compat issues and documentation drift when they are separated. Pulling in okapi or another solution would be invaluable.

ralpha commented 3 years ago

I am starting a new project soon and I'm really hoping to use Rocket, but OpenAPI support is a determining feature. I've looked at okapi but code genning off Rocket inherently requires tight coupling to Rocket which causes compat issues and documentation drift when they are separated. Pulling in okapi or another solution would be invaluable.

I have been working on an update for Okapi to both update to rocket 0.5.0-rc.1 and replace manual implementations with generic traits, where possible. (see master branch atm) Some info can currently not be gathered from Rocket itself, so manual implementations are needed in these cases.

An example where data is missing would be the mime-type (eg "application/json" or "application/octet-stream") of a rocket::data::FromData object. (there are more cases, but this is a simple one to understand)

So if Rocket could provide this data, the coupling could be reduced and things would be both easier to create and maintain (and more accurate in some cases).

@chriskuech I hope Okapi fits your need, if not open an issue and let me know how things can be improve.