vert-x3 / vertx-web

HTTP web applications for Vert.x
Apache License 2.0
1.11k stars 534 forks source link

Add OpenAPI extensions to the Router and Route objects #2412

Closed pmlopes closed 11 months ago

pmlopes commented 1 year ago

Context: https://github.com/eclipse-vertx/vertx-openapi/issues/25

In the router builder, once we can collect the extension information from the contract we should add them to the Router and Route metadata instances where applicable.

pk-work commented 1 year ago

We have 3 sources for extensions:

OpenAPIRoute.getExtensions() should collect the extensions from Path and Operation. If there is a naming conflict Operation extensions win, similar to parameters.

Question: How do we make extensions from the openapi-object accessible?

pmlopes commented 1 year ago

I'm not sure we need new APIs here.

For example, during the createRouter() method here:

https://github.com/vert-x3/vertx-web/blob/60225f3030e4542c6b61a76ca02716c3605b5394/vertx-web-openapi-router/src/main/java/io/vertx/ext/web/openapi/router/impl/RouterBuilderImpl.java#L104-L105

We can use the internal reference to contract to apply the extensions to the router as:

for (Map.Entry<String, ?> extension : contract.getExtensions().entrySet()) {
  router.metadata().put(k, v);
}

And then in the for loops bellow:

https://github.com/vert-x3/vertx-web/blob/60225f3030e4542c6b61a76ca02716c3605b5394/vertx-web-openapi-router/src/main/java/io/vertx/ext/web/openapi/router/impl/RouterBuilderImpl.java#L113-L114

we can add the extensions to the route, just like above (2 times, 1st the route, 2nd the operation extensions):

for (Map.Entry<String, ?> extension : [route|operation].getExtensions().entrySet()) {
  route.metadata().put(k, v);
}
pk-work commented 1 year ago

Let's assume I add extensions to the Path, because I want to have this in all Operations.

Now I want to implement a handler for my OpenAPIRoute. How could I access these extensions?

routerBuilder.getRoute("createPets").addHandler(rc -> {
  rc.currentRoute().metadata().get("x-myExtension");
});

This would require implicit knowledge and maybe conflicts with other metadata on the route.

OpenAPIRoute route = routerBuilder.getRoute("createPets");
route.addHandler(rc -> {
  route.getExtensions().get("x-myExtension");
});

This approach wouldn't need implicit knowledge. Maybe we can even introduce a getExtension("x-myExtension") method.

pmlopes commented 1 year ago

We already add the operation id to the metadata:

https://github.com/vert-x3/vertx-web/blob/60225f3030e4542c6b61a76ca02716c3605b5394/vertx-web-openapi-router/src/main/java/io/vertx/ext/web/openapi/router/impl/RouterBuilderImpl.java#L115-L116

I was assuming we could add the remaining too. But I see the potential issues with occlusion of extensions, though the vert.x metadata works as a chain. 1st check the current route, if not present, look at the router, if present at both, the deepest your are is the value, unless you request the metadata from the router.

But I like the "unopionated" approach you're proposing, where one must explicitly add the extensions if that is the developer's wish.

pk-work commented 1 year ago

I was assuming we could add the remaining too.

Of course can we do it, I didn't said that we can't do it or shouldn't do it. I just want to suggest an additional way to access these extensions, which requires less implicit knowledge.

pmlopes commented 1 year ago

I like your idea of being explicit, this is what defines vert.x as a framework, avoid the magic!

pk-work commented 11 months ago

Its now implemented https://github.com/eclipse-vertx/vertx-openapi/pull/48