-
Notifications
You must be signed in to change notification settings - Fork 9.1k
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
Support an operation to have multiple specifications per path (e.g. multiple POST operation per path) #182
Comments
Real world example - OpenStack Server Actions. I've been trying to convert OpenStack WADL to Swagger and these operations have been a sticking point. There's no real way to describe them right now, because the Swagger doesn't allow path (which is what the WADL uses), nor does it allow "oneOf" or "anyOf" schemas. So I don't see any possible way to describe these services right now. On the other hand, I want Swagger to define an API, not just describe it. That's the whole reason the working group decided to avoid some of these features in the first place - to avoid ambiguity. If this is going to be done it needs to be done in a way that works for:
It's basically a routing problem: given an HTTP request you should know what operation is being called, and this makes it ambiguous. |
+100! Recently we had to change our api because were unable to define multiple post methods per path. So api became uglier in favour of its documentation. |
This is a feature of Swagger's opinion on APIs. For better or worse, it presumes that the signature of an operation is the resource path pattern plus the HTTP verb. To change this would require an alternate mechanism for defining the signature. If we do pick this up in Swagger.next, then let's consider an overloading of a method with some sort of signature property. I'm not sure that this is something that it SHOULD do, but that is how I would tackle it. (and I agree with what @maxlinc said above) |
I recently came across the same problem and would love to have the ability to define the API and associate the same path with multiple endpoints that are still unique. So I'd like to suggest that endpoints are not defined by their paths, but by a user defined key name. More than likely it'll be a domain specific operation name (eg: 'addBookByJson','addBookByBinary' may both have the same path but different endpoints/consumes). Then each endpoint would have a path associated with it instead of 'being' the path directly. Ambiguity is still easy to check based on an equality function of all defined endpoints (which could then be based on implementing platform which might be more applicable rather than defining the equality relation in the swagger API). There are so many ways I could define an endpoint based on an HTTP request. And if swagger is to be a general tool for documentation, then I would much rather see swagger show its opinions in the form of defaults (or the easy path), NOT by limiting functionality when I need to go outside of the norm to support others or implement new ideas! |
+1 |
+1 |
+1 |
2 similar comments
+1 |
+1 |
+1 This would be really fantastic:
|
+1 |
+1
Feels a bit like the tail wagging the dog. |
+1 |
2 similar comments
+1 |
+1 |
What we are doing in the interim is to use /a/b/c: We have customized Swagger UI to hide these tags and remove them from the Try It/curl Each of these I realize that almost none of the existing Swagger ecosystem will work with this, but we need to move forward, and this is the path we're taking. It was the easiest and lowest impact change to Swagger UI and the swagger documents, and it works fairly well. Our expectation is to be able to transform our use to wherever Swagger.Next goes. |
A user can start a com.vmware.xenon.swagger.SwaggerDescriptorService on a host and a swagger 2.0 description is served by default on /discovery/swagger. * add new xenon-swagger module containing a single stateless service * add enumValues to PropertyDescription describing an ENUM * add kind to PropertyDescription describing a PODO * add latest release of Swagger-UI as custom ui of swagger * documentKind is used to refer to swagger Models * fix bug in ServiceDocumentDescription.Builder that assigns a kind of java:lang:Number to Number-typed fields (like in NumericRange) TODOs: * read swagger annotations to provide more details and docs: currently not possible withoug peeking into the service classes * figure out if a service support PATCH/OPTIONS/POST...: not possible without peeking into the service class and looking for overriden handler methods * Swagger 2.0 cannot fully describe a service interface, track this: OAI/OpenAPI-Specification#182 Change-Id: I9d59dd63187c769994fe8b8ce3143e119dc3cdde
+1 |
Another possible format for modelling this, not perfect though either. It comes out of the REST principle that you use the verb. Now REST over HTTP forces verb to be GET,POST,etc and they suggest you use an _method parameter or some override parameter to POST operations to indicate your real verb. So with that in mind we could define a paramter with a special type or mark it someway as your verb-override parameter for the specific end point and then change the verb to what you want. Would look something like this:
With this, anything that falls outside of the standard HTTP verbs are modelled as POST /some/path?_method=copy. It could also then be used for those servers that only support PATCH or other standard HTTP but not as well supported verbs through a method override. |
+1 |
The long-standing work-around is to add a unique URL-fragment to the end of the path. However, if your OpenAPI JSON description is being auto-generated by some library that doesn't support this use-case, then you either need to find a different library or write your own code to generate the OpenAPI JSON. You could also hand-write the OpenAPI JSON :) |
To visually "hide" this |
I encountered same problem when I am writing OpenAPI spec of my OAuth2 server. My workaround is to use path parameter like below (rather than {
"paths": {
"/oauth/{code_grant_endpoint}": {
"post": {
"operationId": "codeGrant",
"parameters": [
{ "name": "code_grant_endpoint", "in": "path", "required": true, "schema": { "type": "string", "enum": [ "token" ] } },
// .... and other parameters ...
],
// ...
},
"/oauth/{client_cred_endpoint}": {
"post": {
"operationId": "clientCredentialsGrant",
"parameters": [
{ "name": "client_cred_endpoint", "in": "path", "required": true, "schema": { "type": "string", "enum": [ "token" ] } },
// .... and other parameters ...
],
// ...
},
// ...
},
} In above example, I defined two operations "codeGrant" and "clientCredentialsGrant". Path of both operations are exactly same: Because of the path parameters in definition ( This way works without any modfication or postprocess in OpenAPI definition consumer side (e.g. openapi-generator). |
Actually the From the spec (emphasis mine):
|
Oh... thank you for comment. It seems work in my case, but now I understand it is implementation specific behavior... Sad for the restriction. |
+1 |
1 similar comment
+1 |
My 5 cent and solution: /myUrl/myRoute/?queryPara1={query1}?queryPara2={query2}:
get:
parameters:
- in: path
name: query1
schema:
type: string
- in: path
name: query2
schema:
type: string
/myUrl/myRoute/?queryPara3={query3}?queryPara4={query4}:
get:
parameters:
- in: path
name: query3
schema:
type: string
- in: path
name: query4
schema:
type: string |
@jon-jon-jon interesting... OpenAPI does not seem to restrict the value of a path to be just |
"it's working fine" suggests that the specification needs to be more clear here (https://spec.openapis.org/oas/v3.1.0#patterned-fields). In order to match the request's path against all the path-item properties, we need to clearly define just what the "path" is. It can't be true that the path both contains and DOESN'T contain the query parameters. Regarding fragments, I think we can be a little more certain, because fragments are not supposed to be handled by servers at all - it's purely a client-side thing. I would certainly regard any attempt by openapi tooling to specify or check the fragment to be an error. |
User agents aren't even expected to send the fragment in the request to the server. |
This was some time ago, but this thread has been a good source of truth, is there chance you could tell me how you removed the tag from the 'Try it out' interface? |
The Moonwalk (OAS 4) proposal has affirmed a principle of operation signatures which will address this use case 🎉 As this cannot be done within the 3.x line, please follow the Moonwalk repo discussions for further developments. |
@handrews with OAS 3.1 failed adoption because of Swagger libraries for more than 3 years, I wonder how long it'll take it to adopt OAS 4 |
@eirnym Swagger is not the only product in the OpenAPI ecosystem. Other major tooling vendors started adding 3.1 support as early as 2 months after 3.1.0's publication. Swagger's late support just ensured that new OAS users looking for modern technologies chose other vendors. From an ecosystem point of view, it's actually better to have multiple competing major vendors rather than a single dominant one. Adoption of 3.1 continues to grow, including in larger organizations less likely to be on the bleeding edge. OAS 3.0.0 was released in 2017. When we published OAS 3.1.0 four years later, OAS 3 still had not really supplanted OAS 2. But by now it has. These things always take more time than anyone would like. That said, we are already looking at ways to make Moonwalk more adoptable. |
I totally agree that swagger is only one of tools to be used for OAS. However, I've observed in few enterprise companies that "We can't use OAS 3.1 because of Swagger and we don't accept any other third party tool". What do you propose for developers to say teams responsible for API in a company to increase popularity of Moonwalk (as a next OAS generation)? |
@eirnym This is a complex topic that probably belongs somewhere other than comments on a random closed/moved issue. But I'll take a shot at it here- this is something that interests me very much, along with ensuring that we have a series of small but useful 3.x releases to both deliver features for users and tooling vendors who are just now getting to 3.1 and make the migration to Moonwalk more smooth when it becomes possible. My personal view (and while as a maintainer I have some write privileges in this repo, I am not in any way speaking as a representative of the project's official position), is that the OpenAPI Initiative has lost the trust of at least significant part of its community. This due to several things, all of which are understandable individually but have added up to a difficult state of affairs:
I think a lot of this had to do with the pandemic. Several people, including myself, became unable to focus on these projects. There have also been some weird things that have been logistically challenging due to unavailability of people who worked on those things in the past, and lack of understanding of how and why things are the way they are. The broken links on the rendered Markdown in GitHub would be the most glaring example. There were also people who felt that with 3.1.0 out, there shouldn't be more 3.0.x releases. And there was no point in doing 3.1.1 when 3.1.0 wasn't implemented yet. Last year things were still moving slowly and sporadically as I got involved again (I was moving pretty slowly and sporadically, too). But there is a huge burst of energy from new and returning people as we kick off 2024, and we are actively working to put our house in order. This is starting with the expansion of the Technical Steering Committee so that we have a full roster of active TSC members. Once we have our governance revived, we'll be able to make more headway on that list of process issues. We've changed the agenda for the weekly Thursday calls to block out time for process and governance at the start of the meeting to make sure we make progress. We've also split Moonwalk out into a Tuesday meeting, leaving the Thursday meeting to focus on 3.x plus governance (we've also considered splitting out the governance work, but at the moment it feels like that's not needed and would be too many meetings). We're also talking about finding some meeting times that suit more time zones and maybe rotating the time slot a bit. Also in that New Year's Cleaning meta-issue, you'll see issues about defining our minor and patch release strategies for 3.x(.y). You'll see that I've proposed an overall philosophy of "smoothing the path to Moonwalk." I'm not the only person advocating for 3.x – I think @lornajane first brought up the need to keep our focus on it and not just rush off to Moonwalk, and she has continued to advocate for it in the calls. I think we have to rebuild trust by clarifying as much as we can for vendors and users in 3.0.x and 3.1.x patch releases (since the majority of users are still on 3.0), and by releasing small, incremental, valuable 3.x releases so that end-users see benefits and signs that their needs are being listened to well before Moonwalk support becomes widespread. Where possible, we should backport Moonwalk features to 3.x to increase convergence (like Python 2.x and 3.x releases when they overlapped). I'm currently going a bit overboard adding new labels to the remaining backlog to figure out the patterns in requests that could help us define coherent and valuable 3.x(.y) releases. I have some other ideas about making the path to moonwalk less of a hug gap to jump across, but I haven't floated them with anyone yet and they're a little too half-baked to write about publicly at this point. But I plan to be in both the Tuesday 4.x and Thursday 3.x calls on a regular basis, pushing for something that is not just "release a de-facto major version that requires a complete architectural re-write every 3 to 4 years." Moonwalk is exciting, but my personal opinion is that we need to tend to the 3.x users, and show that it is worthwhile to move to 3.1 because they will be rewarded with a steady stream of incremental 3.x releases that will make the transition to Moonwalk as smooth as possible when the time comes. |
for the API path `/apis/{group}/{version}/{plural}`. We define a new key `/apis/{group}/{version}/{plural}#[U+200E]` in `custom_objects_spec.json` to work around this limitation. > OpenAPI defines a unique operation as a combination of a path and an HTTP > method. This means that two GET or two POST methods for the same path are not > allowed. — https://swagger.io/docs/specification/paths-and-operations We use the hair space empty character to visually hide this path param from the Swagger UI. closes kubernetes-client#268 Work around was taken from [here][1]. [1]: OAI/OpenAPI-Specification#182 (comment)
for the API path `/apis/{group}/{version}/{plural}`. We define a new key `/apis/{group}/{version}/{plural}#[U+200E]` in `custom_objects_spec.json` to work around this limitation. > OpenAPI defines a unique operation as a combination of a path and an HTTP > method. This means that two GET or two POST methods for the same path are not > allowed. — https://swagger.io/docs/specification/paths-and-operations We use the hair space empty character to visually hide this path param from the Swagger UI. may resolve kubernetes-client#268 Work around was taken from [here][1]. [1]: OAI/OpenAPI-Specification#182 (comment)
for the API path `/apis/{group}/{version}/{plural}`. We define a new key `/apis/{group}/{version}/{plural}#[U+200E]` in `custom_objects_spec.json` to work around this limitation. > OpenAPI defines a unique operation as a combination of a path and an HTTP > method. This means that two GET or two POST methods for the same path are not > allowed. — https://swagger.io/docs/specification/paths-and-operations We use the hair space empty character to visually hide this path param from the Swagger UI. addresses kubernetes-client#268 Work around was taken from [here][1]. [1]: OAI/OpenAPI-Specification#182 (comment)
for the API path `/apis/{group}/{version}/{plural}`. We define a new key `/apis/{group}/{version}/{plural}#[U+200E]` in `custom_objects_spec.json` to work around this limitation. > OpenAPI defines a unique operation as a combination of a path and an HTTP > method. This means that two GET or two POST methods for the same path are not > allowed. — https://swagger.io/docs/specification/paths-and-operations We use the hair space empty character to visually hide this path param from the Swagger UI. addresses #268 Work around was taken from [here][1]. [1]: OAI/OpenAPI-Specification#182 (comment)
with POST actions especially, there can be several unrelated operations that would be better presented to the user as separate POST actions in swagger-ui because they do very different things to the same resource. Each of these different operations should have a unique description string and unique media types to select from and other unique parameters (such as query parameters), and thus have separate presentation in swagger-ui. By simply allowing only just schema overloading, there is no way for me to constrain query parameter A to be used with just media type X, and query parameter B to be used with media type Y. These are implemented as two independent operations and it would be nice to be able to model them independently in Swagger.
So I think a proposal i saw elsewhere to annotate the operations themselves (to provide unique keys in the JSON object) would actually be more flexible than other workarounds to the fact that Swagger only allows one POST per path when a REST API may in fact support many independent POST calls.
i.e. something like
(Initially discussed in #146)
The text was updated successfully, but these errors were encountered: