Skip to content

What is the meaning of multiple schemas in a Content-Type header? #607

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

Closed
danfoygel opened this issue Jun 15, 2018 · 9 comments
Closed

What is the meaning of multiple schemas in a Content-Type header? #607

danfoygel opened this issue Jun 15, 2018 · 9 comments

Comments

@danfoygel
Copy link

Section 10.2 of the latest draft (http://json-schema.org/latest/json-schema-core.html#rfc.section.10.2) gives the following example:

Content-Type: application/json;
          schema="http://example.com/alice http://example.com/bob"

What is the meaning of multiple schemas in a Content-Type header? Does this say that the HTTP response conforms to both the "alice" and "bob" schemas? Or to either the "alice" or "bob" schema? In either of those cases, why wouldn't you express that through a single schema?

How is a well-designed client supposed to process the response when it receives a Content-Type header with multiple schemas?

Thanks,

-Dan

@handrews
Copy link
Contributor

@danfoygel I thought I'd added some guidance on this but clearly I did not. I don't remember if that's because there was disagreement or I just forgot about it.

The most complex use case driving this would be handling API evolution with schemas. So you might have

Content-Type: application/schema-instance+json;
    schema="http://example.com/schemas/thing/1.0.0 http://example.com/schemas/thing/1.1.0"

if the API thinks that it's possible that a given "thing" representation might be valid according to both versions. This would not be done in a single schema because clients are relying on the schema URI to tell them whether it is a version that they recognize.

This response says that a client that knows either the 1.0.0 version of "thing" (and note the versioning is per resource type, not for the whole API) or the 1.1.0 version could both make use of the response. Presumably because those versions are more or less compatible (this is a huge topic and I'm glossing over the subtleties a lot).

I would say that a schema SHOULD be valid against all of the linked schemas, but I've occasionally come up with reasons why it might only be valid against one of them. That might be why there's no guidance in the spec- I don't think I ever really convinced myself one way or the other.

For now, I'd recommend only linking schemas that are expected to be valid, as the "at least one" approach is kind of weird and I'm not sure we should recommend it or not.

@handrews
Copy link
Contributor

@danfoygel feedback/questions on the above ramble is appreciated. I'd like to improve the language in this draft (although no rush on that, it's still a couple months out).

@danfoygel
Copy link
Author

Thanks for the quick response, @handrews.

I agree that "all of" semantics make more sense than "any of", since at least in that case the sender of that header is making a definitive claim about the resource. Definitely would be good to document this, since everyone has to agree on the semantics in order for it to be meaningful.

I can see the scenario you propose, where one client can only process thing 1.0.0, and another client can only process thing 1.1.0. In this case, if the server returns a resource that conforms to both schemas, this can work if the server declares a Content-Type with both schemas.

However, Content-Type Negotiation through the Accept header is presumably the preferred way to accomplish the same scenario, for a variety of reasons. Since that option exists and is more of a standard, I'm wondering if there's any genuine need to also support the multiple-schema pattern?

I think there's also a strong argument for following the analogy of https://tools.ietf.org/html/rfc7231, which allows for multiple media-type values for Accept but not for Content-Type. Similarly, I would recommend allowing multiple schemas in the Accept header but not in Content-Type.

Thanks.

@handrews
Copy link
Contributor

@danfoygel while I see your point of view on multiple schemas, there are quite a few other scenarios to consider.

First, you're assuming that clients are pro-actively negotiating content with Accept. However, many clients will opportunistically make use of schemas. They may ask for something that has a schema (application/schema-instance+json) without asking for a specific schema. Or even just ask for JSON and make use of a schema if it happens to appear.

Schema URIs are also identifiers. So if there are two well-known formats for, say, calendar appointments, but it's possible to write a response that conforms to both, then it is good for that response to link to the schemas for both of those formats. An opportunistic client can see if it recognizes either, and take action based on that. Or, even without recognizing either, it may use other information to make productive use out of the response.

But this is another situation where the two schema URIs cannot be combined into a single schema- the whole point is that those specific two URIs are the ones widely recognized as identifiers. Combining them into a new URI would eliminate their usefulness as well-known identifiers.

RFC 7231 is maddeningly imprecise about how media type parameters can be used in Accept, noting that such usage is rare. While the ABNF for media ranges adds support for wildcarding the full media type or just the subtype, it does not provide any such allowance for parameters. Nor does it allow for parameters with multiple values when the media type itself only allows for single-valued parameters.

It is critically important to allow multiple schemas in Accept, so that a client can indicate all of schemas it finds acceptable. There is no mechanism for saying "only one schema is allowed, except in the HTTP Accept header". Which would be far too HTTP-specific anyway. HTTP is not the only user of media types.

I will also point out that we are looking at using Prefer for a kind of content negotiation in HTTP (see #601), largely due to Accept not really being set up for maximum flexibility with media type parameters. And also because technically, you cannot use any media type parameters with application/json, as the media type itself must opt in to each parameter. application/json has refused to support similar parameters in the past (e.g. "profile").

@handrews handrews added the core label Jun 16, 2018
@danfoygel
Copy link
Author

Thanks @handrews - that makes sense. There are indeed cases where listing multiple schemas in the Content-Type header is the only way to express something.

I want to understand better how you think multiple schemas in Accept should be represented. The two obvious alternatives are as two media types:

Accept: application/json; schema="http://example.com/alice", application/json; schema="http://example.com/bob"

or as two schemas for one media type:

Accept: application/json; schema="http://example.com/alice http://example.com/bob"

I'm not sure if this behavior is already documented somewhere (I didn't see it in the latest draft) but I would propose that the former syntax be used to express that the client will accept a response that conforms to "any of" the schemas, whereas the latter can express that the response must conform to "all of" the schemas. The latter is nicely symmetric with Content-Type, since in both cases space-separated schemas would have "all of" semantics.

In practice, "any of" semantics are of course more useful in an Accept header, and here the existing RFC7231 syntax works nicely, include support for using the q parameter to express relative preferences between alternative schemas.

Thoughts?

@handrews
Copy link
Contributor

@danfoygel I like the "all of" vs "any of" idea, need to think on it a bit but seems like it would work, including the general Accept advantages you mention. I'll definitely add to draft-08 based on this issue so at some point look for a PR linked to this. Probably not in the next few days, though, I've got a lot of backlog to work through.

@danfoygel
Copy link
Author

Thanks @handrews - that sounds great.

@handrews
Copy link
Contributor

@danfoygel finally got around to this- not sure if posting the PR last week notified you or not. It will be up for review for another week-ish.

@danfoygel
Copy link
Author

Thanks! I added one minor comment, but overall this is a really helpful clarification.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: Closed
Development

No branches or pull requests

2 participants