-
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 for multiple request/response models based on headers #146
Comments
Let's say you have your content type param as a path param. Like what Reddit is doing. See this. Then it will be represented like this: swagger: 2
info:
version: "1.0.0"
title: reddit
paths:
/r/{sub}:
get:
responses:
200:
description: HTML
post:
responses:
500:
description: You can't
/r/{sub}.json:
get:
responses:
200:
description: JSON Now imagine the same API wants to use content-header for the response type. We can have another level of abstraction for different content types swagger: 2
info:
version: "1.0.0"
title: reddit
paths:
/r/{sub}:
get:
content-types:
XML:
paramaeters:
-
name: type
in: header
description: Content-Type
responses:
200:
description: HTML
JSON:
paramaeters:
-
name: type
in: header
description: Content-Type
responses:
200:
description: JSON
post:
responses:
500:
description: You can't This is just a raw idea. I don't know if it's even practical |
The first sample @mohsen1 presented is something that can be done today as the content type is being controlled by the path and there's no issue representing it. The second sample is closer to what @jahlborn expected, I assume. I'm not convinced how common this use case is (not saying it doesn't exist though, of course). I'd hope to see a solution that doesn't complicate the spec for users who don't need this feature to avoid complication as much as possible. We're trying to create a spec that's simple enough for people to use without having to deal with complexity if they don't need it. I suspect we'll manage to find an elegant solution for this one though. |
If we were only looking to support different schemas based on media-type, then the current spec isn't very far off. you can already provide a list of media-types in produces and consumes. if you allowed multiple "in:body" request parameters with an additional media-type parameter, then that would cover the requests. the harder part is the responses. ideally, you would want "schema" to instead be "schemas", which is a map from media-type to the Schema Object. This overall design assumes that everything else about the operation is the same other than different formats based on media types. the second example from @mohsen1 is a much bigger change which allows much greater differences in the operation for each media type. |
I like the
|
per design, we don't overload response type definitions for the same response code. |
@fehguy - i understand that this is currently the case, which is why this issue is tagged as "swagger.next". or are you saying this will never be the case, in which case this issue is moot? |
sorry, carry on. I suggest proposing anything with that label--there was a fair amount of discussion in the workgroup about avoiding overloading response types. |
@fehguy - so going back and reviewing that thread, i agree with most of the arguments against overloading in that thread. specifically, you said "Yes, swagger has always had a deterministic response type per operation (combination of http request method + path + http response code)". later you mentioned the proposal to include all the query params, and that you felt that was "ugly". i largely agree with this. while my initial description above does indicate choosing model based on any header, that probably falls into a similar category as all the query parameters. I would agree that the REST ideals aim for the url and http method defining the resource. however, i would argue that the media type is still an important factor. a given resource can have many formats, and that is controlled by the media-type related headers. So, i still think there should be (at least) the ability to specify multiple models for input and output based on media-types. |
For another data point, I will mention that our APIs currently allow overloading of path/methods and use the Content-Type and Accept headers to indicate the representation of the request and response bodies. Thus, a GET or PUT or POST to /a/b/c may allow any of n different, discrete media types (each are different representation of the resource). In particular, we use different media types to distinguish different JSON bodies, i.e.
Of note, we do not rely on just a "file extension" such as .json to determine a response type, So this ability (and the association in swagger-ui of a media type with a schema) |
This feature certainly is going to be part of next version of Swagger. There is no way to not break the standard and have operation overloading. I have another proposal for operation overloading syntax. Here it is: swagger: '2.1'
info:
version: "1.0.0"
title: File
paths:
/file:
get:
responses:
200:
description: Return HTML by default
get[application/vnd.sas.a+json]:
responses:
200:
description: Return JSON
get[application/pdf]:
response:
200:
description: Returns PDF Advantages:
Disadvantages:
Them main conflict is that we are trying to model an API in a tree structure while operations and parameters can not have parent/child or sibling relationships |
@mohsen1 from the comments made by @fehguy, i'm guessing that this would probably only ever be entertained for media-types, not for headers in general. i'm pretty much okay with that. i think that putting the media-type with the method, though, opens up too much freedom for abusing the media-type. the current design of swagger works from the standpoint that a path and http method uniquely define a resource. by overloading at the http method level, you are allowing all the parameters, responses, etc. to be different based on the media-type. this would essentially make the argument that a resource is defined by path, http method, and media-type. in contrast, my compromise proposal at this point, is that path and http method still uniquely define a resource, but that we should allow for different representations of that resource based on media-type (this is essentially what @DavidBiesack is asking for, and basically what the examples i gave in the original description describe). as i said above, i think that using a schemas property (both in responses and in the body parameter) would be a relatively small change from the current swagger spec which would allow for different representations of the same resource, but otherwise keep the rest of the resource's spec unchanged.
|
Definitely agree and think that overloaded schemas looks like a much easier spec change to deal with than overloaded methods. |
However, 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
|
@DavidBiesack - what you're talking about is different than intended by the original topic, and I'd recommend opening a separate thread for it. They may be solved in a similar manner, but providing support for one issue does not guarantee we'll provide support for another. |
@jahlborn - Do you have references to publicly available APIs that use the method of different mime types for different data representations? Of course, I'm not talking about the basic json vs xml but rather the one you were talking about. |
@jahlborn and supports these representations of a GitHub issue:
See GitHub Media Types : |
Thanks @DavidBiesack, the GitHub api is a great example. |
That example shows the versioning representation, but not the difference in modeling. I'd love to see more examples, if you know of any. The first reason, is to see that it is, in fact, a common practice. The second, is that with more examples we can end up having a definition that covers the use case properly with possible support for some edge cases. There's no hurry in providing such samples as it'll be a while before this is actually implemented in the spec. Just feel free to point to additional APIs as you encounter them. |
I disagree; the GitHub API clearly shows the resource representation difference. For a given resource, I can ask for the raw Markdown source; the clean text representation, html representation or full json representation of the same resource. See the Comment Body Properties section where each of these media types is defined. Also for different representations, the Google Drive API provides an analogous mechanism (though query parameters, not via Accept headers) for the exportLinks. I.e. grab a spreadsheet resource out of Google Drive and it will contain media-type specific export links such as
geoserver REST API supports multiple media types via Content-Type, for example POST /styles can consume a |
I'm referring to xml/json interoperability. We're not trying to describe how a response would look differently as a pdf vs xlsx. Github's API doesn't even support XML. The geoserver documentation is unclear as to how the data formats are actually represented by the different content types. |
@webron What do you mean by "xml/json interoperability"? Earlier you wrote
so I was looking for exactly that - different data representations/mime types of the same resource. |
I'm referring to point 1 of the original post, @DavidBiesack. @jahlborn knows what I'm talking about as that's basically what started this issue in the first place. Thank you for looking for samples though, I'm happy to see you're actively trying to pursue it. |
Just did a quick google search, found https://xively.com/dev/docs/api/communicating/data_formats/ . their json and xml formats are similar, but i believe there are differences which would fall out of the current swagger support (particularly the response). it looks like they are constrained by an existing "standard" schema for the xml (which also kind of ties into one of my previous requests for first class xml schema support, Issue #54). |
Here's what I want: consumes:
json: application/json
protobuf: application/vnd.google.protobuf
produces:
json: application/json
protobuf: application/vnd.google.protobuf
paths:
/things:
post:
operationId: post-things
parameters:
- name: json
in: body
description: JSON payload
mime: json
schema:
type: array
items:
type: string
- name: protobuf
in: body
description: Protobuf payload
mime: protobuf
schema:
title: ThingPostMessageProtobuf
responses:
200:
description: OK
schemas:
json:
type: array
items:
type: boolean
protobuf:
title: ThingResponseMessageProtobuf
|
Adding my voice to this thread. I am facing this issue of Content-Type dependent POST body schemas. |
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. 😜 |
Responses are now specified based on media type! 🎉 |
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? |
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 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 |
The schema doesn't really support endless permutations for granularity. You could resolve this on
|
@baynezy well... 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: 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 |
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. { |
@KeithProctor in OpenAPI 3, |
@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 |
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. |
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.
The text was updated successfully, but these errors were encountered: