Closed jahlborn closed 7 years ago
I've been thinking about this problem for a while....
My first preference is to be able to use an array under a path as suggested above by BigSocial on April 27 2015 but that cannot happen until a new Swagger spec is released.
In the meantime, a workaround that I am experimenting with is to use a marker suffix in the paths. It exists only to create an artificially separate path in the Swagger spec, but one which is not really in the API.
Thus, if I want two different POST methods on an endpoint, I could use the following Swagger
"paths" : [
"/models/{modelId}/elements#1" : {
"post" : { ... }
"/models/{modelId}/elements#2" : {
"post" : { ... }
]
These #1
and #2
suffixes would be stripped out when Swagger UI or Swagger Editor Try It out! makes the API call, stripped out in swagger-codegen, etc.
They are 'transient' artifacts just to allow Swagger to describe each abstract API call separately. Swagger UI would call
POST /models/{modelId}/elements
in both cases.
This would allow complete segregation of not only the method but also parameters such as headers, consumes/produces, schema, etc. Thus, if a back end implementation supports the desired overloading, the separate controllers emitted by swagger-codegen would work.
(Some other syntax such as $$1
or {$1}
could be used to avoid ambiguity with # in URLs referring to anchors. The syntax is not important, it is the marker or discriminator in the path that is important).
I think this addresses this issue as well as Open Support an operation to have multiple specifications per path (e.g. multiple POST operation per path) #182
:+1: For different media-types support
Just ran into this as well. I'm going to append some garbage regexp onto the end of one of my paths to get it to display my second POST and consider changing the path completely if this isn't picked up by swagger.next.
Question - will this be extended to query string parameters as well? A number of APIs (including mine) serve different resources based on qs params. I see a number of related issues (https://github.com/swagger-api/swagger-spec/issues/56, https://github.com/swagger-api/swagger-spec/issues/123, https://github.com/swagger-api/swagger-spec/issues/164) but none of them address multiple response objects per query param directly.
@logicbomb - I purposely avoided that in this issue because i knew that it was frowned upon in the original swagger v2 discussions (i menionted that in one of my early comments). And i'm pretty sure that the other issues, e.g. #164 , would include having different response objects based on the query params.
+1 very interested in this getting added in next version. Would love to be able to do GET:/v1/things/{id} and specify that application/json returns #/definitions/thing and application/pdf returns a file.
It's definitely a must-have to support different responses based on content-negotiation. The most important reason for this in my opinion is JSON-LD. The semantic web is finally taking off and if you want Siri, Cortana or Google Now to 'understand' your data, you should start providing JSON-LD, telling machines what the data is about and providing links to external web pages as identifiers so every 'thing' knows what we're talking about.
This means my application/json
response would look like this:
{
name: "Ferrari F50",
brand: "Ferrari"
}
While my application/ld+json
response would look like this:
{
@type: "http://schema.org/Car",
name: "Ferrari F50",
brand: {
@id: "http://dbpedia.org/resource/Ferrari",
@type: "http://schema.org/Brand",
label: "Ferrari"
}
}
Another use case I can imagine is the use of Hypermedia in APIs. Perhaps you want to support both JSON-API (application/vnd.api+json
) as HAL (application/hal+json
) but both rely on completely different response structures.
RAML supports this by simply adding the mime type to an example response, instead of working with models. Perhaps this is something to take a look at!
For clarity, I want to stress out that it is really needed to version data contracts, not resources. Resources pretty much stay the same for a very long time, but data contracts can change more frequently.
I think there was a very good proposal made by @jahlborn in this comment.
This is also similar to the way it is done in RAML 0.8 (cfr. 'Schemas' paragraph) and this works quite well in practice.
What I would enforce is that the media-types must also be 1 tot 1 defined in the "produces"
entry, if not, it is an error. (don't see added value in friendly names as proposed above, it makes it too verbose)
I also again agree with @jahlborn for the post/put solution with multiple in:body entries he proposed, again with the enforcement of the fact that the mime-types must be present in the "consumes"
entry for this case.
I really think it should be limited to these 2 cases, because all we are talking about is the data contract (ie. mime-type set in accept or content-type headers) for the retreived or uploaded 'body'.
Question now to @fehguy is: when can this be added to the spec or what is holding it back? ;-)
Yes this is a frequently requested change and you've summed up the options well. It will break all tooling though and require a major version change. There are other pending requests that is like to see considered for the next version as well. We are getting closer to the candidate list, again the challenge will be breaking tooling across the board, and that is best mitigated by some back compatibility planning. There are over 1500 swagger tooling projects now so it is a big task...
+1
:+1: content negotiation seems to be a fundamental part of a RESTful API, you all really should try to find a way to support it
+1
:+1:
JSON
and ATOM
might not be in same structure. We have been supporting JSON
for sometime and might want to add ATOM
later in an existing API, which most likely will be in a different structure.
+1
+1, especially now that the specification is separate from the implementation, and should no longer inherit the shortcoming which existed in the implementation
On Mon, Jan 25, 2016 at 10:14 AM, hjoliveira notifications@github.com wrote:
+1
— Reply to this email directly or view it on GitHub https://github.com/OAI/OpenAPI-Specification/issues/146#issuecomment-174589818 .
@mparker - fwiw, this was never 'not added' to the spec because of the implementation. It was 'not added' because nobody asked for it when the current version was being discussed (believe it or not). Unfortunately, this ticket was opened shortly after the version was finalized and we couldn't just go and change it (like for other requests as well). While can't guarantee, I seriously doubt this will not make it to the next release (regardless of implementations).
@webron many may have assumed that it is or would be there, as Accept/Content-Type header are essential in HTTP protocol. Here is an example how java's ws rs as exposes it :
@Produces({MediaType.APPLICATION_JSON, ResourceConsts.APPLICATION_YAML})
@Consumes({MediaType.APPLICATION_JSON, ResourceConsts.APPLICATION_YAML})
public interface MyResource {
The specification of accept/response content type is very naturally specified and list is extended/modified over time.
@okigan - that is supported today in the spec. What's not supported is saying if application/json
return structure X and if application/YAML
return structure Y. Another take is support output versioning with the mimetype as the OP points out, that's also not supported. Not sure if you were part of the work group around 2.0 (which was public) - we discussed the smallest of the details. Unfortunately we had some misses, and hopefully the next version will mend the major misses and add some new and exciting features.
@webron I guess I assumed, one could add a vendor specific type to that list -- which could be a different schema:
@Produces({"application/vnd.mycompany.type", MediaType.APPLICATION_JSON, ResourceConsts.APPLICATION_YAML})
@Consumes({MediaType.APPLICATION_JSON, ResourceConsts.APPLICATION_YAML})
public interface MyResource {
+1 here, the City of Helsinki APIs cannot be fully specified ATM.
:+1: For different media-types support too
+1 - got an endpoint treated differently based on the Accept header and can't properly document.
Parents: #586, #574.
+1: we respond with JSON or Atom (XML) depending on the Accept
header provided by the client. And allow JSON or Atom (XML) request bodies with POST
, PATCH
, and PUT
with corresponding Content-Type
header
👍 for endpoints treated differently based on the Accept
header.
Some APIs support accepting different models in the POST body, based on whether the body is an Object or an Array.
When generating code, we can easily add an if
statement to check if the body is an Object or an Array. It should validate that the input type matches the model anyway. So this level of model differentiation is very easy to implement.
Negotiating on Accept
and Content-Type
is a great place to start. However, it would be ideal if this (or something like it) could support the other options for negotiation: Prefer
header, Accept-Encoding
, Accept-Language
, etc.
Perhaps basing the handling on HTTP's Vary
header would feel familiar.
Any updates on this? When will this be implemented and released? We really need this fix. Thanks!
Meanwhile, trying to express JFrog Artifactory REST API, I've faced w/ this issue at the very beginning of my learning of OpenAPI Specification. Here is a real life example:
both have the same URI patterns, but different MIME type of results (which is supposed to be used to distinct them). And there is no way to express that nowadays :(
:+1: I have exactly the use case with different schemas for different media types on the same path.
Adding my voice to this thread. I am facing this issue of Content-Type dependent POST body schemas. I am left with two options. Either the API replicates exactly what is in my spec, and I have to find a workaround in the API because the spec does not support defining different schemas; or I have missing information in my spec to be able to implement the behaviour in the API.
Schemas which vary by content type has been added to the 3.0 spec
Thanks, @fehguy! Good to know. I'll be following the release of version 3.0
@fehguy URL or it didn't happen. :stuck_out_tongue_winking_eye:
Responses are now specified based on media type! :tada:
Where can I find out more about the release schedule for V3?
@baynezy Currently we have a RC0, which is an implementer's draft. I guess we'll have one or some more RCs fixing the currently found issues, and the last one will be promoted to the final release. As far as I know, there is no timeline here – it all depends on the feedback we get from implementers, and the time the contributors find.
Where can I learn more about media-type-specific requests/responses?
Where can I learn more about media-type-specific requests/responses?
The following areas of the specification should be a good start, including the examples which follow each section:
What about content negotiation depending on request header like Prefer
(what @BigBlueHat mentioned in his comment)?
I have a POST API endpoint that returns the same response code and same content type, but actual returned schema varies based on Prefer header. For example, when Prefer is return=minimal
only an ID of resource is returned, but when it's return=representation
a whole resource is returned.
The schema doesn't really support endless permutations for granularity. You could resolve this on Accept
like this:-
Accept: application/json; prefer=minimal
@baynezy well... prefer
is a header (re: RFC 7240), not a media type parameter.
Here's an example (though there are certainly others) of using it "in the wild": https://www.w3.org/TR/annotation-protocol/#container-representation-preferences
It was attempting to create an OpenAPI doc for that API that ultimately brought about this comment: https://github.com/OAI/OpenAPI-Specification/issues/146#issuecomment-235136624
So...perhaps this needs a new issue (as this one's closed)?
@BigBlueHat @mpavkovic I just write the schema such that it works with both the minimal and representation forms. There are several ways you can make the specific alternative more clear. I think the real question is around exactly what you need to convey beyond "this resource understands Prefer
" and ensuring that each variation validates.
I have a related question to this thread but going in the opposite direction. I want to find out if it is possible to create an endpoint that allows a parameter to accept multiple inbound data types? Such as allowing a JSON parameter to be a number as well as a string. This is simply a convenience to our users and would be extremely friend for them.
{ "someParam": "1" } or (would be allowed) { "someParam": 1 }
@KeithProctor in OpenAPI 3, {"oneOf": [{"type": "number"}, {"type": "string"}]}
should work.
In standard JSON Schema, you can also just do {"type": ["number", "string"]}
@handrews ... This is for a swagger definition? Right?
@KeithProctor Is Swagger still on OpenAPI 2? If that's the case then I think you just can't do this in Swagger. OpeanAPI 2 did not support oneOf
.
Sorry I didn't get back to you. This seamed to work in 2.x. The type with list method that is.
We created a rest web service with Nancy in a C# project. Now we want to use Open API as standard documentation, but we have a problem. We keep each path version in header of request with special parameter called "GenerationVersion", now I don't know how can I represent multiple version of specific path with specific http method.
I guess this is a 2.0+ request as 2.0 is already "released".
Basically, there is currently no way to express a single path which may have different request/response formats based on additional criteria, namely headers. two possible scenarios:
If supporting different responses for arbitrary headers is too big of a change, just supporting multiple media-types (for request and response) would be sufficient for the cases described here.