Skip to content

Add support for the alternate link relation #133

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 4 commits into from
Aug 16, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
12 changes: 11 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5809,7 +5809,7 @@ <h3>LoadDocumentCallback</h3>
<ol class="changed">
<li>Create a new {{Promise}} <var>promise</var> and return it.
The following steps are then executed asynchronously.</li>
<li>Set <var>document</var> to the body retrieved from
<li id="LoadDocumentCallback-step-2">Set <var>document</var> to the body retrieved from
the resource identified by <a data-link-for="LoadDocumentCallback">url</a>,
or by otherwise locating a resource associated with <a data-link-for="LoadDocumentCallback">url</a>.
When requesting remote documents the request MUST prefer <a>Content-Type</a> <code>application/ld+json</code>
Expand All @@ -5824,6 +5824,13 @@ <h3>LoadDocumentCallback</h3>
<li>Set <var>documentUrl</var> to the location of the retrieved resource
considering redirections (exclusive of HTTP status <code>303</code> "See Other" redirects
as discussed in [[?cooluris]]).</li>
<li>If the retrieved resource's <a>Content-Type</a> is not <code>application/ld+json</code>
nor any media type with a <code>+json</code> suffix as defined in [[RFC6839]],
and the response has an HTTP Link Header [[RFC8259]] using the <code>alternate</code> link relation
with type `application/ld+json`,
set <var>url</var> to the associated <code>href</code> relative to the previous <var>url</var>
and restart the algorithm from <a href="#LoadDocumentCallback-step-2">step 2</a>,
ensuring that <var>documentUrl</var> is set to the original <var>url</var>.</li>
<li>If the retrieved resource's <a>Content-Type</a> is <code>application/json</code>
or any media type with a <code>+json</code> suffix as defined in [[RFC6839]]
except <code>application/ld+json</code>,
Expand Down Expand Up @@ -6372,6 +6379,9 @@ <h2>Changes since JSON-LD Community Group Final Report</h2>
a context. When this is set, vocabulary-relative IRIs, such as the
<a>entries</a> of <a>node objects</a>, are expanded or compacted relative
to the <a>base IRI</a> and the <a>vocabulary mapping</a> using string concatenation.</li>
<li>In the <a>LoadDocumentCallback</a>, if the retrieved content is not `application/ld+json`
and there is a link header with `rel=alternate` and `type=application/ld+json`, redirect
to that content.</li>
Copy link
Contributor

Choose a reason for hiding this comment

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

This probably needs to be discussed (it is not just editorial).

This would create a different behaviour when the document is accessed directly, than when it is accessed through the "link header indirection". So I am not a big fan of the idea.

I would rather encourage the author of the JSON-LD document to explicitly set the base to the URL o the non-JSON-LD document, if that is the behaviour they intend.

Copy link
Member Author

Choose a reason for hiding this comment

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

The PR is definitely prospective, as the issue is still marked to be discussed, but I wanted to get it out there and see the consequences. The link header shouldn’t affect any json format, but would affect html content. What document base should be applied can be debated, but using the original document has precedent.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I think I disagree with @pchampin ... and that we want to treat this like we do with redirects, which I believe uses the original document. The argument for doing what @pchampin suggests would be that there's no way to know ahead of time what the final document will be, so you couldn't set the base to it, whereas you could set the base to the original document if you wanted it to stick.

But, processors could have a flag to switch to this other behavior. It seems to me that the sensible default would be the original document. Especially given the way that we expect this feature to be used ... which is that the linked document is really a hidden implementation detail. If you wanted to use the linked document directly you would have specified it instead of some, e.g., HTML document.

Copy link
Member Author

Choose a reason for hiding this comment

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

👎 to introducing another flag, though. If the document should have some specific base different from the originally referenced resource, it can use @base.

My thought in using the original resource base, rather than the referenced document, is essentially the same reasoning that lead to the semantics of HTTP status 303 for range-14 considerations.

Copy link
Member

Choose a reason for hiding this comment

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

If this use of alternate (which comes from HTML primarily) is meant to supplant using content negotiation, then the expectation would be (afaict) that the original resource URL would (semantically) be the correct base URL--which I think agrees with what @gkellogg said above.

Once the alternate is retrieved it should experientially be like getting a content negotiated response with a Content-Location set to the alternate and having Location still be set to the original Request-URI--which is how content negotiation plays out.

Copy link
Member

Choose a reason for hiding this comment

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

What I mentioned on the call Friday was that the only definition of rel="alternate" (that I'm aware of) is in https://html.spec.whatwg.org/multipage/links.html#rel-alternate

The summary definition is "Gives alternate representations of the current document." but the follow-on expansion on it includes "The meaning of this keyword depends on the values of the other attributes."

The examples in that section include alternate CSS styles (i.e. rel="alternate stylesheet"), Atom/RSS alternate representations (i.e. rel="alternate" type=""), and using it for language [content] negotiation (i.e. rel="alternate" hreflang="" +/- type="").

So, using alternate here to accomplish a pre-flight content negotiation (of sorts) is not without its precedence conceptually. However, none of that directly answers the base URI situation...as in the closest experiential case (language negotiation) the browser would navigate to the new resource based on language preferences--thereby acting more like a 30* redirect than like content negotiation.

Copy link
Member

Choose a reason for hiding this comment

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

Additionally, if we stick with alternate, we may need to require other link parameters (or type parameters) to clarify that this is a representation of the current document as a context vs. a representation of the current document expressed in JSON-LD (i.e. as a data document).

We could use the existing context profile URL (which is used as a rel in Interpreting JSON as JSON-LD). The experience would be similar to referencing a data document as the context of another data document.

Copy link
Member Author

Choose a reason for hiding this comment

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

I understand the parallel with HTTPRange-14 . But I see nowhere in those documents an indication that relative IRIs in the target document should be resolved against the source document's IRI...

There's a discussion in Cool URIs:

... Each of the RDF documents would contain statements about the appropriate resource, using the original URI, e.g. http://www.example.com/id/alice, to identify the described resource.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but they do not say that a relative URI could or should be used for that...

Copy link
Member Author

Choose a reason for hiding this comment

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

At this point, I think you need to raise a new issue for discussion, because we seem to have quite different views on this, and discussing in a merged PR isn't a good way to be sure we resolve it.

</ul>
</section>

Expand Down
50 changes: 50 additions & 0 deletions tests/remote-doc-manifest.jsonld
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,56 @@
},
"input": "remote-doc/0013-in.json",
"expect": "remote-doc/0013-out.jsonld"
}, {
"@id": "#tla01",
"@type": ["jld:PositiveEvaluationTest", "jld:ExpandTest"],
"name": "Redirects if type is text/html",
"purpose": "Load an alternate link if type is not ld+json and rel=alternate.",
"option": {
"httpLink": "<la01-alternate.jsonld>; rel=\"alternate\"; type=\"application/ld+json\""
},
"input": "remote-doc/la01-in.html",
"expect": "remote-doc/la01-out.jsonld"
}, {
"@id": "#tla02",
"@type": ["jld:PositiveEvaluationTest", "jld:ExpandTest"],
"name": "Does not redirect if type is application/ld+json",
"purpose": "Load an alternate link if type is not ld+json and rel=alternate.",
"option": {
"httpLink": "<la02-alternate.jsonld>; rel=\"alternate\"; type=\"application/ld+json\""
},
"input": "remote-doc/la02-in.jsonld",
"expect": "remote-doc/la02-out.jsonld"
}, {
"@id": "#tla03",
"@type": ["jld:PositiveEvaluationTest", "jld:ExpandTest"],
"name": "Does not redirect if link type is not application/ld+json",
"purpose": "Load an alternate link if type is not ld+json and rel=alternate.",
"option": {
"httpLink": "<la03-alternate.json>; rel=\"alternate\"; type=\"application/json\""
},
"input": "remote-doc/la03-in.json",
"expect": "remote-doc/la03-out.jsonld"
}, {
"@id": "#tla04",
"@type": ["jld:PositiveEvaluationTest", "jld:ExpandTest"],
"name": "Does not redirect if type is application/json",
"purpose": "Load an alternate link if type is not ld+json and rel=alternate.",
"option": {
"httpLink": "<la04-alternate.jsonld>; rel=\"alternate\"; type=\"application/ld+json\""
},
"input": "remote-doc/la04-in.json",
"expect": "remote-doc/la04-out.jsonld"
}, {
"@id": "#tla05",
"@type": ["jld:PositiveEvaluationTest", "jld:ExpandTest"],
"name": "Base remains that of original document",
"purpose": "Load an alternate link if type is not ld+json and rel=alternate.",
"option": {
"httpLink": "<la05-alternate.jsonld>; rel=\"alternate\"; type=\"application/ld+json\""
},
"input": "remote-doc/la05-in.html",
"expect": "remote-doc/la05-out.jsonld"
}
]
}
6 changes: 6 additions & 0 deletions tests/remote-doc/la01-alternate.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "alternate"
}
16 changes: 16 additions & 0 deletions tests/remote-doc/la01-in.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<html>
<head>
<title>Content to be skipped</title>
<script type="application/ld+json">
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "skipped"
}
</script>
</head>
<body>
<p>This content should be skipped</p>
</body>
</html>
3 changes: 3 additions & 0 deletions tests/remote-doc/la01-out.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[{
"http://example.org/content": [{"@value": "alternate"}]
}]
6 changes: 6 additions & 0 deletions tests/remote-doc/la02-alternate.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "alternate"
}
6 changes: 6 additions & 0 deletions tests/remote-doc/la02-in.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "not skipped"
}
3 changes: 3 additions & 0 deletions tests/remote-doc/la02-out.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[{
"http://example.org/content": [{"@value": "not skipped"}]
}]
6 changes: 6 additions & 0 deletions tests/remote-doc/la03-alternate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "alternate"
}
6 changes: 6 additions & 0 deletions tests/remote-doc/la03-in.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "not skipped"
}
3 changes: 3 additions & 0 deletions tests/remote-doc/la03-out.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[{
"http://example.org/content": [{"@value": "not skipped"}]
}]
6 changes: 6 additions & 0 deletions tests/remote-doc/la04-alternate.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "alternate"
}
6 changes: 6 additions & 0 deletions tests/remote-doc/la04-in.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"content": "not skipped"
}
3 changes: 3 additions & 0 deletions tests/remote-doc/la04-out.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[{
"http://example.org/content": [{"@value": "not skipped"}]
}]
7 changes: 7 additions & 0 deletions tests/remote-doc/la05-alternate.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"@context": {
"@vocab": "http://example.org/"
},
"@id": "",
"content": "alternate"
}
17 changes: 17 additions & 0 deletions tests/remote-doc/la05-in.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<html>
<head>
<title>Content to be skipped</title>
<script type="application/ld+json">
{
"@context": {
"@vocab": "http://example.org/"
},
"@id": "",
"content": "skipped"
}
</script>
</head>
<body>
<p>This content should be skipped</p>
</body>
</html>
4 changes: 4 additions & 0 deletions tests/remote-doc/la05-out.jsonld
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[{
"@id": "https://w3c.github.io/json-ld-api/tests/remote-doc/la05-in.html",
"http://example.org/content": [{"@value": "alternate"}]
}]