Skip to content

"collection" and "item" usage #412

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

Merged
merged 1 commit into from
Oct 1, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions jsonschema-hyperschema.xml
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@
<!ENTITY rfc5789 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5789.xml">
<!ENTITY rfc5988 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.5988.xml">
<!ENTITY rfc6570 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6570.xml">
<!ENTITY rfc6573 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6573.xml">
<!ENTITY rfc6901 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.6901.xml">
<!ENTITY rfc7231 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.7231.xml">
<!ENTITY rfc7240 SYSTEM "http://xml.resource.org/public/rfc/bibxml/reference.RFC.7240.xml">
@@ -879,6 +880,87 @@
Note that these relationship values are case-insensitive, consistent with their
use in HTML and the <xref target="RFC5988">HTTP Link header</xref>.
</t>
<section title="&quot;collection&quot; and &quot;item&quot; links">
<t>
<xref target="RFC6573">RFC 6573</xref> defines and registers
the "item" and "collection" link relations. A well-known design pattern
in hypermedia is to use a collection resource to create a member of the
collection and give it a server-assigned URI. When using HTTP, or a protocol
such as CoAP that is explicitly analogous to HTTP, this is done by POST-ing
a representation of the individual resource to be created to the collection
resource.
</t>
<t>
Resources that are the target of a "collection" link using HTTP or an analogous
protocol in JSON Hyper-Schema MUST NOT assign semantics other than resource
creation to POST (or the analogous method in non-HTTP protocols).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this one. Maybe this about what is meant by "resource creation".

Typically, I'm thinking about using the collection+item pattern to describe relationships. For instance, consider a Article tags Tag relationship model, POST-ing to the URI some article's tags relationship (something like /articles/1/tags/) may lead to different results depending on the payload and server semantics: it could set a relation between the article and an existing tag (identified by payload) without modifying the underlying entities, or it could add a new tag entity with a relation set. The latter case arguably falls into "resource creation" semantics, but it's not obvious for the former, though one could argue that a new relation is created.

Also, what about a PUT or a DELETE request? Should we specify the expected behavior as well?

In fact, I wonder if we shouldn't discuss this "protocol semantics" topic separately and let this PR focus on documenting the pattern (where each link should be, how to set the context with anchorPointer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dlax There is no concern with PUT and DELETE, whose semantics are clear.

The problem here is that creating a resource with a server-assigned identifier is not part of HTTP's uniform interface. But it is one of the most common operations that is done in APIs, and it is flatly impossible to write a generic hypermedia client without it.

Take a look at application/collection+json and application/maze+xml, which are both given as the examples of use of "collection" and "item" RFC. Both of these specify creation-via-POST semantics for collections based on these link relations.

For your tag example, there is nothing problematic about any of those behaviors. The resource has to define what it means to be created. The point is not to tie "resource creation" to "put a thing in a database", or any other implementation. Both of the options you give are implementation details. The point is to ensure that if this exact relation is used, that POSTing to such a resource doesn't do something totally unexpected and damaging, like reboot the application. Which would otherwise be a completely valid thing for a resource to do in response to a POST (because literally anything is valid for POST).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't even say that creation has to be supported. It just says not to completely break clients that need SOME generic clue as to how to accomplish this. Link relation types are the only correct way to specify semantics.

And to be clear, these are link/resource semantics, NOT protocol semantics. That's kind of the entire point- there is nothing in HTTP that officially carries these semantics. Nothing we do in this media type changes that.

But per RFC 5988bis:

Link relation types can also be used to indicate that the target resource has particular attributes, or exhibits particular behaviours

We are following existing patterns, referenced in the RFC that defines these link relation types, to constrain behavior in order to make it possible to implement a generic hypermedia client using JSON Hyper-Schema.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@handrews I've thinking about this a bit more...

I think that what made me worry is that the text about "resource creation and POST" is located at the very beginning of the section whereas I would have expected to first read about how to use the collection+item pattern in a JSON Hyper Schema document. (In fact, I'm not that worried and the example I posted was mostly rhetorical.)

So I was about to suggest to move this part (starting from "A well-known design pattern..." to where this comment is attached) later in the section, but I'm actually not sure if it'd make still sense. So if it doesn't, I can live with it as is :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dlax yeah, that's fair, and I think I can get it to introduce the creation pattern less abruptly. If it's OK with you I'll just note that for the rewrite, as I'll almost certainly be reworking the text anyway.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's OK with you I'll just note that for the rewrite, as I'll almost certainly be reworking the text anyway.

Sure, that works too.

</t>
<t>
The <xref target="submissionSchema">"submissionSchema"</xref> field for the
link SHOULD be identical to the schema of the representations of the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "identical" here?
For instance, if I'd like to add constraints on the submissionSchema (like a required or the "readOnly": true from the example below, assuming it's not already on /thing's schema), is this allowed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't supposed to say "identical", actually. I just kept rewriting it, and then changing ti back, and apparently forgot I still needed to work on it. At various times it was "analogous to" or "compatible with".

What I want to convey is that the representation used to create a resource here should be more-or-less the same as the one used in "targetSchema" for the individual resource's "self" link. But It can, of course, differ in things like the server-generated "id" being absent during creation but required in "targetSchema". I actually handle that by just marking it read-only and not required in the schema but documenting that it's always present when retrieved from the server.

I'm not sure how to explain exactly what should and shouldn't be allowed here. I don't even want there to be some hard and fast rule, and it definitely needs to be a SHOULD or RECOMMENDED instead of a MUST.

Any suggestions welcome.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the postamble of the example, I used "matching", but didn't explain what that meant either.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"compatible with" sounds good to me; what you meant is clear enough I think (I just ticked on "identical", but now that's fine) and follows common sense so that it probably does not need more explanation.

collection's items, as indicated by the "item" link. RFC 6573 identifies
the "collection" and "item" link relation types as reciprocal, so the
context resource of an "item" link MAY be treated as a collection, even if
no explicit "collection" link is defined.
</t>
<figure>
<preamble>
The first of these hyper-schemas describes an individual "thing",
while the second describes a collection of "things". Note that the
"targetSchema" of the individual thing's "self" link is the same
as the "submissionSchema" of its "collection" link.
</preamble>
<artwork>
<![CDATA[{
"$id": "http://example.com/schemas/thing",
"type": "object",
"properties": {
"id": {
"type": "integer",
"readOnly": true
}
},
"links": [{
"rel": "self",
"href": "/things/{id}",
"targetSchema": {"$ref": "#"}
}, {
"rel": "collection",
"href": "/things"
"targetSchema": {"$ref": "thing-collection"}
"submissionSchema": {"$ref": "#"}
}]
}]]>

<![CDATA[{
"$id": "http://example.com/schemas/thing-collection",
"type": "array",
"items": {
"allOf": [{"$ref": "thing"}]
"links": [{
"anchorPointer": "",
"rel": "item",
"href": "/things/{id}",
"targetSchema": {"$ref": "thing"}
}]
},
"links": [{
"rel": "self",
"href": "/things",
"targetSchema": {"$ref": "#"},
"submissionSchema": {"$ref": "thing"}
}]
}]]>
</artwork>
<postamble>
In the hyper-schema for the collection, the "item" link also demonstrates
the usage of "anchorPointer", as the context of that link must be the
entire collection, rather than the individual array element to which the
link is attached. The collection's self link also supports a
"submissionSchema" matching that of its "item" link's "targetSchema".
</postamble>
</figure>
</section>

<section title="Security Considerations for &quot;self&quot; links">
<t>
@@ -1584,6 +1666,7 @@ GET /foo/
&rfc4151;
&rfc5789;
&rfc5988;
&rfc6573;
&rfc7231;
&rfc7240;
</references>