micronaut-projects / micronaut-core

Micronaut Application Framework
http://micronaut.io
Apache License 2.0
6.09k stars 1.07k forks source link

Multiple paths in @Controller annotation #6977

Open chrisparton1991 opened 2 years ago

chrisparton1991 commented 2 years ago

Feature description

I have a requirement to support path-based versioning for my API endpoints. The twist is that a versionless path must also be supported.

Say I have a /books endpoint. The following paths need to be accepted:

Future versions (e.g. /v2/books) would be implemented as separate controllers, but I would like to bind the versioned and versionless URLs to the same controller if possible.

My current workaround is a funky regex, but it's not great:

@Controller("/{version:books|v[0-9.]+/books}")

One option is to allow multiple Controller paths, similar to #2188:

@Controller(uris = {"/books", "/v1/books"})

Any ideas or suggestions would be appreciated!

graemerocher commented 2 years ago

A subclass that overrides the path?

chrisparton1991 commented 2 years ago

I tested the subclass option and that works, thanks.

With the subclass I need to repeat my class-level annotations (e.g. @ExecuteOn, @Secured) and pass through injected constructor parameters so there's a bit of code duplication involved.

Allowing multiple paths on a single @Controller annotation would be an ergonomic improvement, but I have multiple workarounds so I'm happy for this to be closed (unless you think it's a worthwhile feature).

yawkat commented 2 years ago

we could also make @Controller repeatable

ericsnx commented 1 year ago

Is there any news on this? just came across the same scenario, thanks for the workaround.

yawkat commented 1 year ago

it's in my feature backlog but i have no timeline

ee-usgs commented 1 year ago

Another use case on this: Blue/Green deployments.

Say that my production data service is canonically available at:

HOST/data/* --> [Currently deployed data services app]

When I do a new production deploy, I deploy a new instance of my service app and I enter an AWS LoadBalancing ListenerRule that sends urls like this to it:

HOST/data-candidate/* --> [My newly deployed Micronaut App 'CandidateApp']

I test on the HOST/data-candidate/* url. When all looks good, I update the ListenerRule to send traffic from the canonical url to that same 'CandidateApp'

HOST/data/* --> ['CandidateApp' (without redeploy) now becomes canonical version]

So, my app with all of its end points needs to be flexible in that first part of the url. Ideally during local testing they wouldn't even require that /data-ANYTHING/ part because its not really defined - I'd like to accept anything in there.

What I would really like is to be able to define the context of the entire app that way so I don't need to add that complexity on all the controllers, but I don't see a way to do that.