-
Notifications
You must be signed in to change notification settings - Fork 843
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
Rethink extension negotiation #614
Comments
Where did fielding make that comment? I didn't even know he was aware.
|
I accidentally copied and pasted the wrong link when I posted it, should be fixed in the OP now. |
ah interesting. I kinda agree with @royfielding here, though I obviously disagree with 'meaningless' |
Taken from the same comment:
So this is the approach we are taking. He goes on to state:
He's correct about this and this is also clearly stated in json-api's format section. Some of the examples in that issue are invalid. As for the "meaningless" comment: I suspect it was made because the media type is in the vendor tree and not the standards tree. It may have been made without even connecting |
Yup, I've been worried this too. (I asked Roy on twitter about the other issue, which is what prompted his comment.) My tentative feeling now is that:
EDIT: I started writing my comment before @dgeb published his, so sorry about the cross-noise. The above was written mostly in response to @steveklabnik and @daliwali. I agree with @dgeb also that the "meaningless" quote and the stuff about DQUOTE tokens is beside the point. But I still think there's a substantive point here about how we could refine extension negotiation to make it easier to reason about. |
The way I interpret his comment is that the base spec is meaningless given that parameters may override any part of it. I think this issue is closed prematurely because the point hasn't been discussed: negotiating parameters may be the wrong approach, especially if those parameters alter the format of the base spec. Also I made a syntactic error by omitting the double quotes, but it doesn't affect the point. |
Yeah, this is something i worry about. |
Ok, reopening to discuss making extensions additive-only. |
Well, keep in mind that I only looked at this issue — I don't know what your specification says. JSON is a meaningless data format, and API certainly doesn't add any meaning, and the name doesn't even use the vnd tree properly, so my conclusion is that the media type is a meaningless example. Note that, if you do have a lot of meaning attached to that name, that makes it a poor media type name for something that does have meaning. Use a distinct name, like all the other media types. |
The name "JSON API" sounds like a generic term for any JSON-over-HTTP implementation, and bound to cause confusion for everyone, including those who have heard of the spec (do they mean their API uses JSON, or that it follows the "JSON API" spec?) The main use case for this spec seems to be for tightly coupled client-side applications (case in point: Ember Data). I could throw out some name suggestions but it's probably already too late for a name change. |
Alright, this comment is completely out of scope for this issue, but I need to close out my thoughts somewhere. In short, I see that you already registered the media type name, which means you might as well keep using it. Please understand that, if I were the expert that reviewed the registration, it would have been rejected. Placing a generic, standardizable media type in the vnd tree is just abusing the registration process. Of course, this makes no difference to HTTP or any application thereof, and is still better than using an unregistered type. What I mean by a meaningless type is what a client might decide by looking at the type name. In this case, all they can really decide is that they should invoke a JSON parser and should expect some common structure according to your spec. That's not much. I can see why a client might want to use such a type in Accept, but not why it would want to negotiate on the basis of parameters of that type. If you expect an extension to only be implemented by some clients in a way that other implementations cannot simply ignore, then you should give it a different media type. If the purpose of this type extension is to supply an extended representation, such as a full traversal of a collection instead of just the top page, then that is a different resource and should have a different URI. Supply a link instead. Note that this is a very common problem among folks working on RESTful APIs. Half seem to think that all resources are collections and each representation must be complete (e.g., Siren). The other half seems to think that all resources are pages (e.g., Atom) and everything must be a blog. Neither is right. Some resources are collections, some resources are pages, some resources are indexed results, some resources are graph trees, some resources are images. All of them can show the same data in different ways and still be separate resources. A resource's value is as much a reflection of its consistency across representations (sameness over time) as it is the data it provides. |
Another off-topic comment: IMHO, the name of the spec is its weak point. It is like calling your child Homo Sapiens -- despite being factually correct, I doubt anybody would do that. Even though some like taxonomy-based names (e.g., Sun DHCP Server, Sun Identity Manager, etc.), I guess their hidden intention is to make it difficult to find information about these things on the web. However, selection of name is parent's privilege, so this discussion is indeed late, and it will become too late in about a week... |
The media type name is settled, so let’s get back to talking about extensions. (Also, ping @bintoro, who helped with the initial design.) I want to put forward what I think the goals for the extension system should be and how I’ve been thinking about the different types of extensions. I still don’t have a preferred negotiation system, but I’m pretty sure the current one isn’t what we want, and I think this is important to resolve pre-1.0. Given how close we are to launch, I want to share my thoughts ASAP, even though they're half-baked, to see what others think and to prompt discussion. Hopefully you guys will have ideas for how to specify extension constraints and a real negotiation system using these ideas. Ok, here goes. It seems like the goals are:
The second and third goals seem to imply that we should put some limits on extensions. Also, given that we can always loosen the constraints on extensions later—but we can’t really tighten them post 1.0—it seems like we should air on the side of over-constraining extensions now rather than under constraining them. For those constraints, the first and third goals seem to imply that we want, at root, is for the extensions to be additive in some sense. But I see at least three meaningful senses of “additive”:
Ok, I’ll leave it there for now and follow up in a subsequent comment with thoughts about potential designs and the design space I’ve been exploring. I’m confident that we can come up with a pretty simple design with constructs powerful enough to cover all these cases, it’ll just require some thinking. I'm looking forward to hearing ideas others have too! |
@ethanresnick: In #574 I suggested to use an own namespace for extensions (very similar to your proposal #603) to avoid conflicts - but that's only one problem. Other thinks to consider (in addition to your points):
|
Some further observations on the types of extensions:
I think the above suggests that we should have two fundamental types of extensions that the design should revolve around: profiles, which have these nice composability invariants, and what I'll call the "type-1 extensions", for lack of a better term, that have more power. |
Some thoughts on constraining "type-1 extensions": As I mentioned in my initial post, constraining type-1 extensions at all isn't strictly necessary. Even if they blatantly conflict with the base spec, either at the time of their authoring or down the line (if the base spec adds a similar feature), this won't cause problems for clients as long as the client has explicitly opted in to the extension's meaning. That said, I still think we ought to put some constraints in place to discourage or ensure that "type-1 extensions" don't redefine the semantics of payloads that are already valid under the base spec and to discourage them from using different payload structures to more-or-less duplicate base spec features. (This is goal 3 from my original post.) Below is one constraint regime I've been thinking about for accomplishing the above, that I'd like feedback on:
Let's look at what these constraints cost us and what they give us:
Thoughts? |
On JSON-LD and prefixing: I'd really like it to be possible for a JSON-LD extension on top of JSON-API to be a "type-2" extension and therefore easier to integrate, since I think JSON-LD will only grow in importance. But the only way for a JSON-LD extension to be type two is for the spec to allow type-two extensions to put keys anywhere, at least if they're @-prefixed. But, as we're also going to make type-two additions to the base spec over time, those extension-added keys have to be known to not conflict with future base spec keys, which points the way toward requiring that unofficial type-two extensions use prefixed keys. And, once you have prefixed keys, there's no need for the |
@ethanresnick we don't have a fixed time to tag 1.0 tomorrow. But we will tag 1.0 tomorrow. I am following your comments from a taxonomical perspective (delineating the types of extensions) but I am unclear how these delineations will coalesce into changes to the base specification. As far as I'm concerned, the most important aspect of any extension is that it is an agreed upon contract between client and server. I don't favor buckets such as an I am hopeful that we can keep the rules for extensions rather open-ended and allow different "types" of extensions to evolve organically, using this specification as a baseline. I will re-read your comments above and additional thoughts in the morning. Thanks for thinking deeply about this! |
@royfielding I would also add that people confuse resource with endpoint; in a distributed architecture, binding communication logic to business logic creates an 'architectural cross cutting concern'. This is the way the original API Pattern works as it was intended for centralized architectural... never distributed architectures. To fix this, you have to abstract the communication logic from the business logic so that you can share and synchronize the communication data (ie I/O state). https://developers.redhat.com/blog/2017/10/12/new-api-pattern/ |
Profiles are now in 1.1, see #1268. What's next here? |
@wimleers Nothing, at least for the time being. |
Closing this as extension and profile negotiation has been settled in v1.1. I think most importantly extensions are now additive only. |
I had a bad feeling about implementing the official extensions, or really any extensions at all to the spec, since extensions may completely break the base specification.
In a comment regarding content negotiation, Roy Fielding writes:
"meaningless media type like vnd.api+json"... ouch ;)
The text was updated successfully, but these errors were encountered: