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

@ID tag for each @Router #1095

Open
YC opened this issue Jan 1, 2022 · 8 comments
Open

@ID tag for each @Router #1095

YC opened this issue Jan 1, 2022 · 8 comments
Labels

Comments

@YC
Copy link

YC commented Jan 1, 2022

Is your feature request related to a problem? Please describe.
When there's a controller which handles two path/routes, it would be nice to specify an ID for each route.

// @ID get-user-me
// @Router /users/me [get]
// @ID get-user-param
// @Router /users/{param} [get]

Currently, an expected error arises:
duplicated @id annotation 'get-user-info' found in 'GET /users/1', previously declared in: 'GET /users/me'

Describe the solution you'd like
A possible annotation is seen above or perhaps more cleanly:

// @Router get-user-me /users/me [get]
// @Router get-user-param /users/{param} [get]

With ID optionally provided for backward compatibility.

Describe alternatives you've considered

  • Don't specify @ID, which works without error but for a route like /api/compat/v1/{param}/..., the autogenerated id can become quite messy
  • Duplicate the annotations

Additional context
N/A

@ubogdan
Copy link
Contributor

ubogdan commented Jan 1, 2022

It's not possible to describe 2 endpoints as you did in the example above.

On the other hand, your proposal conflicts with OAS 2 specs and the implementation allready done here #865.

operationId
Each operation may specify a unique operationId. Some code generators use this value to name the corresponding

@ubogdan ubogdan added the invalid label Jan 1, 2022
@YC
Copy link
Author

YC commented Jan 1, 2022

Thanks for the quick response.

Currently, with the following example:

// GetStringByInt example
// @Summary Add a new pet to the store
// @Router /users/me [get]
// @Router /users/1 [get]
func GetStringByInt(w http.ResponseWriter, r *http.Request) {
	// write your code
}

swag produces:

info:
  contact: {}
  description: This is a sample server Petstore server.
  title: Swagger Example API
  version: "1.0"
paths:
  /users/1:
    get:
      responses: {}
      summary: Add a new pet to the store
  /users/me:
    get:
      responses: {}
      summary: Add a new pet to the store
swagger: "2.0"

This double @Router functionality is documented in the README.

Since swag produces multiple operations in the yaml/json when there are multiple @Router, I believe there will be no conflict with the OpenID specifications or #865 in assigning an unique ID to each route/operation. e.g.:

info:
  contact: {}
  description: This is a sample server Petstore server.
  title: Swagger Example API
  version: "1.0"
paths:
  /users/1:
    get:
      operationId: get-user-param
      responses: {}
      summary: Add a new pet to the store
  /users/me:
    get:
      operationId: get-user-me
      responses: {}
      summary: Add a new pet to the store
swagger: "2.0"

@ubogdan
Copy link
Contributor

ubogdan commented Jan 18, 2022

Your last example is simple, and it can be reduced to :

// @Router /users/{id} [get]

Let's take the following example, which is complete CRUD:

// @Param        id   path      int  true  "User ID"
// @Param   user   body model.User true  "Some ID"
// @Success      200  {object}  model.User
// @Failure      400  {object}  httputil.HTTPError
// @Router /users [get]
// @Router /users [post]
// @Router /users/{id} [get]
// @Router /users/{id} [put]
// @Router /users/{id} [Delete]

Now, please answer the following questions, and if you think it's still a good idea, let us know.

  • on which routes the user param is required?
  • on which routes the id param is required
  • can you "assume" the delete method will return a user.Model response?
  • what if the routes are not related to the same entities (model.User, model.Account, model.Roles) ?

I hope this will make clear enough why we are avoiding these shortcuts.

Thanks
Bogdan

@ubogdan
Copy link
Contributor

ubogdan commented Jan 18, 2022

Similar request: #797

@YC
Copy link
Author

YC commented Jan 19, 2022

@ubogdan Many thanks for looking into my use case in detail.
Unfortunately, I wrote that example as a minimal way to explain this issue, but it didn't communicate across the point that it's not possible to merge the params.

In reality, there is one controller function for many routes, like /v1/users/{user}/heartbeats, /compat/wakatime/v1/users/{user}/heartbeats, /users/{user}/heartbeats etc. which all use the same controller, and I'd like to be able to specify a unique id for each of those @Router routes.
If you want to take a look, definitions are currently duplicated in empty functions in the current implementation.
I thought that wasn't ideal, so I tried to specify multiple @Router in the annotation of the controller. I then found that it's not possible to specify a unique @ID for each router, and hence raised this feature request.

To refer to your CRUD example above, I'd like to give each @Router a unique id, which I believe is not currently possible.
The rationale for wanting a unique id (@ID) is to have nicer links in swagger-ui (from operationId in the yaml/json).

@jwschmidt
Copy link

@ubogdan @YC What there ever a resolution to this? I've got the same issue where have two routers with one controller. One has a path parameter and one doesn't. When the docs are generated each show the path parameter.

I'd also like to have a different summary/description for each of them if possible.

@YC
Copy link
Author

YC commented Dec 20, 2022

@jwschmidt Not that I'm aware of, unfortunately.

@kettlecat6
Copy link

kettlecat6 commented Mar 30, 2023

same issue too.

finally I did this:

// @Id Handler_route1
// @Route /route1/xxx
func router1Handler(...){return originalHandler(...)}
// @Id Handler_route2
// @Route /route2/xxx
func router2Handler(...){return originalHandler(...)}
// @Id Handler_route3
// @Route /route3/xxx
func router3Handler(...){return originalHandler(...)}

// swag annotations removed
func originalHandler(...){}

also, handlers changed at here: ctx.HTTPRouter().POST()

on the other hand, could we support multi annotations on one function?like this:

// @Id Handler_route1
// @Route /route1/xxx
// //param,success,failed ...
//
// @Id Handler_route2
// @Route /route2/xxx
// //param,success,failed ...
//
// @Id Handler_route3
// @Route /route3/xxx
// //param,success,failed ...
func originalHandler(...){}

plus: we may need some separators other than blank lines.

I hope that with swag, it would be possible to generate three distinct documents using a single function annotation

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

No branches or pull requests

4 participants