Hi

Am 14.04.2014 um 10:52 schrieb Alexander Klimetschek <aklim...@adobe.com>:

> Thanks Roy for clarifying things.

Indeed and I will reply to that on a separate message.

> 
> I think what it boils down to is that the only real thing that you'd want to 
> move from the sling url (path info) to an accept header would be the 
> extension = mimetype, in case you support multiple variants (say html, json, 
> xml, ...). The selector part is highly server-specific, and should be 
> transparent to the client, so one should rather send out the right hyperlinks 
> to the clients with the right annotations so that the client can make the 
> choice what URL to use, but not have it build the URL or build the right 
> accept header.
> 
> So what about automatically handling the accept header in Sling wrt to 
> extensions, based on a configurable mime type mapping?
> 
> Plain example:
> - resource /content/foo
> - resource type for foo has "json.jsp", "html.jsp" and "xml.jsp"
> - valid requests so far: /content/foo.json, /content/foo.html, 
> /content/foo.xml
> - new: requesting /content/foo with accept header
> - if mimetype in accept header ("application/json") has a mapping to say 
> "json" extension, it would resolve to the "json.jsp"

Right, that's basically what I am proposing.

> - and maybe it's a good idea to use a redirect to /content/foo.json instead 
> of rendering it right away

Maybe not; If the server can handle the /content/foo w/Accept request it should 
IMHO handle it. The point is just that from an URL perspective /content/foo and 
/content/foo.json are two distinct resources - even though the representations 
may be the same (JSON syntax).

The advantage of /content/foo.json, though, is that there is no out-of-band 
(sort of) content negotiation but the URL itself stipulates the representation. 
It may be blurring the distinction between locating the resource (/content/foo) 
and negotiating representation (.json). But it has big advantages in terms of 
cacheability (not requiring a Vary header), access control, human recognition 
(if only for debugging and error recovery), as well as 

> 
> Selector example is more tricky:
> - resource /content/foo
> - resource type for foo has "one.json.jsp", "two.json.jsp"
> - valid requests so far: /content/foo.one.json, /content/foo.two.json
> - should we / can we support a request with /content/foo.one plus accept 
> header application/json?

I don't think so, that would be confusing. Which is why my proposal would be 
for the case of only looking at the Accept header if there is no extension in 
the request (and hence by definition no selector and suffix)

> - or should we allow negotiation on the final URL /content/foo.two.json with 
> accept = text/html would redirect to /content/foo.two.html ?

I agree with Robert that this might be a collision, yet Sling wouldn't consider 
the Accept header if the extension and selector(s) have been extracted already. 
Hence Sling would not realize this collision.

> 
> With suffix it gets even more tricky, as it comes after and thus requires the 
> extension in the URL:
> - /content/foo.json/mysuffix

Well, if Sling does not recognize an extension on the URL neither selectors nor 
suffix will be recognized. Hence for a suffix to be seen, an extension is 
always required in the URL. That is essentially related to the fact that Sling 
first finds the resource and uses the part of the URL past not directly 
addressing the resource to extract the extension, selectors, and suffix from.

> - could allow the same redirect on the final URL
> 
> Anything else, say "selector" and "suffix" don't really have a match in the 
> accept header and are server-specific semantics, which a generic HTTP client 
> does not know about. You'd need to transport this information together with 
> the links in your responses in a semantical format (say html with rel= 
> annoations), and the client has logic following the semantics of this media 
> type to choose the right link. But if it has chosen, there is no advantage of 
> encoding this in an extra header; it's actually more complicated than just a 
> full string.

I agree, that this really is the essence of it all: The links also indicate 
representation to be used simplifying the client-side application.

Regards
Felix

> 
> The support would only come in once there is the right resource chosen, but 
> it's just a matter of supporting different output formats for different 
> clients, without having to encode this in the URLs up front. I.e. you can 
> already send out /content/foo links to your clients and then later add 
> support for a new media type without having to touch any URLs.
> 
> Cheers,
> Alex
> 
> On 13.04.2014, at 23:24, Roy T. Fielding <field...@gbiv.com> wrote:
> 
>> On Apr 7, 2014, at 12:24 AM, Felix Meschberger wrote:
>> 
>>> TL;DR: Use Accept header to set request's selectors and extension. So an 
>>> example Accept content type of "application/x-players+json" would set the 
>>> selector string to "players" and the extension to "json".
>>> 
>>> We always touted Sling to be a platform for REST-ful web applications. But 
>>> we cheated a bit in that we "invented" request selectors and extensions for 
>>> content negotiation instead of using the HTTP Accept header. The reason for 
>>> this cheating was pure pragmatism since in Browsers the easy way to 
>>> influence requests is basically just URLs and request parameters.
>>> 
>>> Hence we built all request processing, prominently script/servlet selection 
>>> on these selectors and extensions. And this proved highly effective.
>>> 
>>> Still, trying to define "pure" REST-ful APIs we can assume applications to 
>>> be able to set the HTTP Accept header and to be able to define clean URLs 
>>> without selectors and extensions.
>> 
>> I think this is confusing REST with several other concepts.
>> For example, "Cool URIs don't change" is a principle that TimBL
>> often talks about, but it is orthogonal to REST.  It is important
>> for bookmarks, home pages, and reference longevity.
>> 
>> REST requires that all important resources be identified;
>> it doesn't say one kind of URI is better than another.
>> It certainly doesn't say that proactive content negotiation is better
>> than non-negotiated resources, since the latter is far superior for
>> caching.  What it does say is that a negotiated resource is not
>> the same resource as a non-negotiated resource, since they
>> do not have the same expectations.
>> 
>> And there is no such thing as an impure RESTful API.
>> An application is either designed according to REST or it isn't,
>> and an API either supports that or it doesn't.
>> 
>>> So for a browser we want to support something like:
>>> 
>>>> GET /teams/fcbasel.html HTTP/1.0
>>>> Host: soccer.example.com
>>> 
>>> while for REST-ful APIs more something like:
>>> 
>>>> GET /teams/fcbasel HTTP/1.0
>>>> Host: soccer.example.com
>>>> Accept: application/x-players+json
>> 
>> You might want to support that for the sake of having
>> a content negotiated identifier, but it isn't any more
>> RESTful than the first example.
>> 
>> In general, x- is not an appropriate prefix for media types.
>> Sling should not encourage their use.
>> 
>>> What if Sling would convert the Accept content type 
>>> "application/x-players+json" into
>>> 
>>>> selectors = [ "players" ]
>>>> selectorString = "players"
>>>> extension = "json"
>>> 
>>> This could be done in the Sling Engine's SlingRequestPathInfo constructor 
>>> under the following conditions:
>>> 
>>> * Extension (and optional selectors) have not derived from the URL yet
>>> * Accept header has a single content type (Browsers generally send a list 
>>> of supported types)
>>> * Accept header is an application type
>>> * The sub type is converted to selector and extensions, where "+" is used 
>>> as the separator
>>> 
>>> WDYT ?
>> 
>> I think being able to route requests to resources based on negotiation
>> header fields (or any request header field) is useful, but beware of
>> how this impacts access control by location.  It is important that
>> the server not lose track of the fact that it received "/teams/fcbasel"
>> as the request target, which might have different access controls
>> than "/teams/fcbasel.players.json".  This can be a problem in deployments
>> where an external server (gateway) performs security checks based on
>> the request target if that server is unaware that the application server
>> will reinterpret the request based on the Accept field's value.
>> 
>> For example, consider when the origin server has
>> 
>>  /teams/fcbasel.players.json
>>  /teams/fcbasel.private.json
>> 
>> and they have different authentication requirements (outside Sling).
>> We don't want the client (attacker) to be able to bypass access
>> controls by manipulating the (typically uncontrolled) Accept
>> field value.
>> 
>> Note that this kind of resource resolution also requires that
>> a Vary header field be set in the response.
>> 
>> What httpd does is allow a URI (or directory) to have an option set
>> for multiviews (or some other negotiation mechanism), which is invoked
>> only if the request target is not found.  This allows negotiated and
>> non-negotiated resources to exist in the same place with the
>> non-negotiated resource winning any request that might be ambiguous.
>> 
>> Regardless, please note that the notion of RESTful systems preferring
>> proactive content negotiation is a myth.  If anything, RESTful systems
>> prefer reactive negotiation, client-side scripting (code on demand), or
>> specific relationship names as a means of selecting from multiple
>> variant URIs.  In other words, more links, with the client choosing
>> the one that best fits their purpose/understanding/version.
>> 
>> 
>> Cheers,
>> 
>> Roy T. Fielding                     <http://roy.gbiv.com/>
>> Senior Principal Scientist, Adobe   <http://www.adobe.com/>
>> 
> 

Reply via email to