You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@sling.apache.org by Felix Meschberger <fm...@adobe.com> on 2014/04/07 09:24:47 UTC
Support REST-ful APIs
Hi all
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.
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
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 ?
Regards
Felix
RE: Support REST-ful APIs
Posted by Rob Ryan <rr...@adobe.com>.
Felix Meschberger wrote:
* Extension (and optional selectors) have not derived from the URL yet
One of the lessons I think I see from how selectors & extensions are working in the face of creation requests to non-existent resources is that there should be a way to *override* what is derived from the existing resolution process. Consider that some URLs end up containing period characters which have nothing to do with a desire for a selector or extension, a prominent example is user ids.
-Rob Ryan
-----Original Message-----
From: Felix Meschberger [mailto:fmeschbe@adobe.com]
Sent: Monday, April 07, 2014 12:25 AM
To: dev@sling.apache.org
Subject: Support REST-ful APIs
Hi all
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.
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
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 ?
Regards
Felix
Re: Support REST-ful APIs
Posted by Bertrand Delacretaz <bd...@apache.org>.
On Mon, Apr 7, 2014 at 11:20 AM, Julian Sedding <js...@gmail.com> wrote:
..
> - other headers, e.g. Accept-Language, could also be easily supported...
Good point, it shows that plugins are welcome in this area.
-Bertrand
Re: Support REST-ful APIs
Posted by Julian Sedding <js...@gmail.com>.
+1 for cachable requests with the Vary-header!
Regards
Julian
On Mon, Apr 7, 2014 at 4:52 PM, Robert Munteanu <ro...@lmn.ro> wrote:
> On Mon, Apr 7, 2014 at 5:50 PM, Marius Petria <mp...@adobe.com> wrote:
>> Just a question on this. Isn't pushing the format information into headers making caching more complicated?
>
> It _should_ work if Sling adds the 'Vary: Accept' header.
>
> Robert
>
>>
>> Regards,
>> Marius
>>
>>> -----Original Message-----
>>> From: Carsten Ziegeler [mailto:cziegeler@apache.org]
>>> Sent: Monday, April 07, 2014 4:28 PM
>>> To: dev@sling.apache.org
>>> Subject: Re: Support REST-ful APIs
>>>
>>> I haven't thought in detail about this, but if we go such a way we should
>>> think of improving the resolve() method of the resource resolver in some
>>> way.
>>> Today, when a request comes in, the full path is used to find the resource,
>>> it's then shortened until an existing resource is found. If we have a request
>>> which targets the resource and the accept header defines the
>>> extension/selector, then there is no need for such an expensive search
>>> mechanism anymore.
>>>
>>> Regards
>>> Carsten
>>>
>>>
>>> 2014-04-07 7:59 GMT-06:00 Felix Meschberger <fm...@adobe.com>:
>>>
>>> > Hi
>>> >
>>> > Ok, it is not exactly arbitrary logic. Turns out that content types of
>>> > the style
>>> >
>>> > > application/someformat+somesyntax
>>> >
>>> > are pretty common (see [1], [2]). Also when talking about REST-ful
>>> > APIs I expect some application on the other (client) side and this
>>> > will in general not come with a list of content types but with a
>>> > single one asking for a concrete representation.
>>> >
>>> > To have a plugin, you need to define and export an API and you have to
>>> > take care about backwards compatibility and evolution. I don't exactly
>>> > see where such a travel would lead to right now.
>>> >
>>> > As to other headers: This is about content type negotiation which
>>> > involves as per the HTTP spec the Accept header. The Accept-Language
>>> > header is for the language to be used for the representation of the
>>> > resource but does not have an influence on the content type.
>>> >
>>> > Regards
>>> > Felix
>>> >
>>> > [1] http://www.iana.org/assignments/media-types/media-types.xhtml
>>> > [2]
>>> > https://github.com/osgi/design/blob/master/rfcs/rfc0189/rfc-0189-Http_
>>> > Service_Updates.pdf?raw=true
>>> >
>>> > Am 07.04.2014 um 11:20 schrieb Julian Sedding <js...@gmail.com>:
>>> >
>>> > > I agree with Bertrand. Generally, I'm in favor of supporting the
>>> > > Accept
>>> > header.
>>> > >
>>> > > However coding an arbitrary logic into Sling Engine (or some other
>>> > > core bundle) does not sound good to me.
>>> > >
>>> > > The benefits of a pluggable solution would be
>>> > > - preservation of modularity and
>>> > > - the implementation of some "special" logic could live in a "contrib"
>>> > > bundle, where it's easier to drop support, if the idea turns out to
>>> > > be not so good.
>>> > > - other headers, e.g. Accept-Language, could also be easily supported.
>>> > >
>>> > > Regards
>>> > > Julian
>>> > >
>>> > >
>>> > > On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
>>> > > <bd...@apache.org> wrote:
>>> > >> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger
>>> > >> <fm...@adobe.com>
>>> > wrote:
>>> > >>> ...I would prefer to not go over board, at least not initially,
>>> > >>> and
>>> > keep it simple and covering simple use cases....
>>> > >>
>>> > >> I like simple but what I object to is burning this into the Sling
>>> > >> core
>>> > >> - what you suggest is based on somewhat arbitrary rules (single
>>> > >> content-type etc) which I don't feel good burning into the core. An
>>> > >> extension point for setting selectors + extensions is not rocket
>>> > >> science.
>>> > >>
>>> > >> -Bertrand
>>> >
>>> >
>>>
>>>
>>> --
>>> Carsten Ziegeler
>>> cziegeler@apache.org
>
>
>
> --
> Sent from my (old) computer
Re: Support REST-ful APIs
Posted by Robert Munteanu <ro...@lmn.ro>.
On Mon, Apr 7, 2014 at 5:50 PM, Marius Petria <mp...@adobe.com> wrote:
> Just a question on this. Isn't pushing the format information into headers making caching more complicated?
It _should_ work if Sling adds the 'Vary: Accept' header.
Robert
>
> Regards,
> Marius
>
>> -----Original Message-----
>> From: Carsten Ziegeler [mailto:cziegeler@apache.org]
>> Sent: Monday, April 07, 2014 4:28 PM
>> To: dev@sling.apache.org
>> Subject: Re: Support REST-ful APIs
>>
>> I haven't thought in detail about this, but if we go such a way we should
>> think of improving the resolve() method of the resource resolver in some
>> way.
>> Today, when a request comes in, the full path is used to find the resource,
>> it's then shortened until an existing resource is found. If we have a request
>> which targets the resource and the accept header defines the
>> extension/selector, then there is no need for such an expensive search
>> mechanism anymore.
>>
>> Regards
>> Carsten
>>
>>
>> 2014-04-07 7:59 GMT-06:00 Felix Meschberger <fm...@adobe.com>:
>>
>> > Hi
>> >
>> > Ok, it is not exactly arbitrary logic. Turns out that content types of
>> > the style
>> >
>> > > application/someformat+somesyntax
>> >
>> > are pretty common (see [1], [2]). Also when talking about REST-ful
>> > APIs I expect some application on the other (client) side and this
>> > will in general not come with a list of content types but with a
>> > single one asking for a concrete representation.
>> >
>> > To have a plugin, you need to define and export an API and you have to
>> > take care about backwards compatibility and evolution. I don't exactly
>> > see where such a travel would lead to right now.
>> >
>> > As to other headers: This is about content type negotiation which
>> > involves as per the HTTP spec the Accept header. The Accept-Language
>> > header is for the language to be used for the representation of the
>> > resource but does not have an influence on the content type.
>> >
>> > Regards
>> > Felix
>> >
>> > [1] http://www.iana.org/assignments/media-types/media-types.xhtml
>> > [2]
>> > https://github.com/osgi/design/blob/master/rfcs/rfc0189/rfc-0189-Http_
>> > Service_Updates.pdf?raw=true
>> >
>> > Am 07.04.2014 um 11:20 schrieb Julian Sedding <js...@gmail.com>:
>> >
>> > > I agree with Bertrand. Generally, I'm in favor of supporting the
>> > > Accept
>> > header.
>> > >
>> > > However coding an arbitrary logic into Sling Engine (or some other
>> > > core bundle) does not sound good to me.
>> > >
>> > > The benefits of a pluggable solution would be
>> > > - preservation of modularity and
>> > > - the implementation of some "special" logic could live in a "contrib"
>> > > bundle, where it's easier to drop support, if the idea turns out to
>> > > be not so good.
>> > > - other headers, e.g. Accept-Language, could also be easily supported.
>> > >
>> > > Regards
>> > > Julian
>> > >
>> > >
>> > > On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
>> > > <bd...@apache.org> wrote:
>> > >> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger
>> > >> <fm...@adobe.com>
>> > wrote:
>> > >>> ...I would prefer to not go over board, at least not initially,
>> > >>> and
>> > keep it simple and covering simple use cases....
>> > >>
>> > >> I like simple but what I object to is burning this into the Sling
>> > >> core
>> > >> - what you suggest is based on somewhat arbitrary rules (single
>> > >> content-type etc) which I don't feel good burning into the core. An
>> > >> extension point for setting selectors + extensions is not rocket
>> > >> science.
>> > >>
>> > >> -Bertrand
>> >
>> >
>>
>>
>> --
>> Carsten Ziegeler
>> cziegeler@apache.org
--
Sent from my (old) computer
RE: Support REST-ful APIs
Posted by Marius Petria <mp...@adobe.com>.
Just a question on this. Isn't pushing the format information into headers making caching more complicated?
Regards,
Marius
> -----Original Message-----
> From: Carsten Ziegeler [mailto:cziegeler@apache.org]
> Sent: Monday, April 07, 2014 4:28 PM
> To: dev@sling.apache.org
> Subject: Re: Support REST-ful APIs
>
> I haven't thought in detail about this, but if we go such a way we should
> think of improving the resolve() method of the resource resolver in some
> way.
> Today, when a request comes in, the full path is used to find the resource,
> it's then shortened until an existing resource is found. If we have a request
> which targets the resource and the accept header defines the
> extension/selector, then there is no need for such an expensive search
> mechanism anymore.
>
> Regards
> Carsten
>
>
> 2014-04-07 7:59 GMT-06:00 Felix Meschberger <fm...@adobe.com>:
>
> > Hi
> >
> > Ok, it is not exactly arbitrary logic. Turns out that content types of
> > the style
> >
> > > application/someformat+somesyntax
> >
> > are pretty common (see [1], [2]). Also when talking about REST-ful
> > APIs I expect some application on the other (client) side and this
> > will in general not come with a list of content types but with a
> > single one asking for a concrete representation.
> >
> > To have a plugin, you need to define and export an API and you have to
> > take care about backwards compatibility and evolution. I don't exactly
> > see where such a travel would lead to right now.
> >
> > As to other headers: This is about content type negotiation which
> > involves as per the HTTP spec the Accept header. The Accept-Language
> > header is for the language to be used for the representation of the
> > resource but does not have an influence on the content type.
> >
> > Regards
> > Felix
> >
> > [1] http://www.iana.org/assignments/media-types/media-types.xhtml
> > [2]
> > https://github.com/osgi/design/blob/master/rfcs/rfc0189/rfc-0189-Http_
> > Service_Updates.pdf?raw=true
> >
> > Am 07.04.2014 um 11:20 schrieb Julian Sedding <js...@gmail.com>:
> >
> > > I agree with Bertrand. Generally, I'm in favor of supporting the
> > > Accept
> > header.
> > >
> > > However coding an arbitrary logic into Sling Engine (or some other
> > > core bundle) does not sound good to me.
> > >
> > > The benefits of a pluggable solution would be
> > > - preservation of modularity and
> > > - the implementation of some "special" logic could live in a "contrib"
> > > bundle, where it's easier to drop support, if the idea turns out to
> > > be not so good.
> > > - other headers, e.g. Accept-Language, could also be easily supported.
> > >
> > > Regards
> > > Julian
> > >
> > >
> > > On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
> > > <bd...@apache.org> wrote:
> > >> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger
> > >> <fm...@adobe.com>
> > wrote:
> > >>> ...I would prefer to not go over board, at least not initially,
> > >>> and
> > keep it simple and covering simple use cases....
> > >>
> > >> I like simple but what I object to is burning this into the Sling
> > >> core
> > >> - what you suggest is based on somewhat arbitrary rules (single
> > >> content-type etc) which I don't feel good burning into the core. An
> > >> extension point for setting selectors + extensions is not rocket
> > >> science.
> > >>
> > >> -Bertrand
> >
> >
>
>
> --
> Carsten Ziegeler
> cziegeler@apache.org
Re: Support REST-ful APIs
Posted by Carsten Ziegeler <cz...@apache.org>.
I haven't thought in detail about this, but if we go such a way we should
think of improving the resolve() method of the resource resolver in some
way.
Today, when a request comes in, the full path is used to find the resource,
it's then shortened until an existing resource is found. If we have a
request which targets the resource and the accept header defines the
extension/selector, then there is no need for such an expensive search
mechanism anymore.
Regards
Carsten
2014-04-07 7:59 GMT-06:00 Felix Meschberger <fm...@adobe.com>:
> Hi
>
> Ok, it is not exactly arbitrary logic. Turns out that content types of the
> style
>
> > application/someformat+somesyntax
>
> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I
> expect some application on the other (client) side and this will in general
> not come with a list of content types but with a single one asking for a
> concrete representation.
>
> To have a plugin, you need to define and export an API and you have to
> take care about backwards compatibility and evolution. I don't exactly see
> where such a travel would lead to right now.
>
> As to other headers: This is about content type negotiation which involves
> as per the HTTP spec the Accept header. The Accept-Language header is for
> the language to be used for the representation of the resource but does not
> have an influence on the content type.
>
> Regards
> Felix
>
> [1] http://www.iana.org/assignments/media-types/media-types.xhtml
> [2]
> https://github.com/osgi/design/blob/master/rfcs/rfc0189/rfc-0189-Http_Service_Updates.pdf?raw=true
>
> Am 07.04.2014 um 11:20 schrieb Julian Sedding <js...@gmail.com>:
>
> > I agree with Bertrand. Generally, I'm in favor of supporting the Accept
> header.
> >
> > However coding an arbitrary logic into Sling Engine (or some other
> > core bundle) does not sound good to me.
> >
> > The benefits of a pluggable solution would be
> > - preservation of modularity and
> > - the implementation of some "special" logic could live in a "contrib"
> > bundle, where it's easier to drop support, if the idea turns out to be
> > not so good.
> > - other headers, e.g. Accept-Language, could also be easily supported.
> >
> > Regards
> > Julian
> >
> >
> > On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
> > <bd...@apache.org> wrote:
> >> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger <fm...@adobe.com>
> wrote:
> >>> ...I would prefer to not go over board, at least not initially, and
> keep it simple and covering simple use cases....
> >>
> >> I like simple but what I object to is burning this into the Sling core
> >> - what you suggest is based on somewhat arbitrary rules (single
> >> content-type etc) which I don't feel good burning into the core. An
> >> extension point for setting selectors + extensions is not rocket
> >> science.
> >>
> >> -Bertrand
>
>
--
Carsten Ziegeler
cziegeler@apache.org
Re: Support REST-ful APIs
Posted by Julian Sedding <js...@gmail.com>.
Hi Felix
> As to other headers: This is about content type negotiation which involves as per the HTTP spec the Accept header.
The HTTP 1.1 spec defines the following headers for
content-negotiation, I quote: "Accept (section 14.1), Accept- Charset
(section 14.2), Accept-Encoding (section 14.3), Accept- Language
(section 14.4), and User-Agent (section 14.43)" (see section 12.1
Server-driven Negotiation [0]). Additionally, an implementation is
free to vary the response based on any aspect of the request.
I understand that you are trying to solve your use-case and I like the
idea of supporting content-negotiation in Sling. What I don't want,
however, is another ad-hoc solution baked into the core of Sling - I
fear that these make Sling harder to maintain, refactor and enhance.
Regards
Julian
[0] http://www.w3.org/Protocols/rfc2616/rfc2616-sec12.html
On Mon, Apr 7, 2014 at 3:59 PM, Felix Meschberger <fm...@adobe.com> wrote:
> Hi
>
> Ok, it is not exactly arbitrary logic. Turns out that content types of the style
>
>> application/someformat+somesyntax
>
> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I expect some application on the other (client) side and this will in general not come with a list of content types but with a single one asking for a concrete representation.
>
> To have a plugin, you need to define and export an API and you have to take care about backwards compatibility and evolution. I don't exactly see where such a travel would lead to right now.
>
> As to other headers: This is about content type negotiation which involves as per the HTTP spec the Accept header. The Accept-Language header is for the language to be used for the representation of the resource but does not have an influence on the content type.
>
> Regards
> Felix
>
> [1] http://www.iana.org/assignments/media-types/media-types.xhtml
> [2] https://github.com/osgi/design/blob/master/rfcs/rfc0189/rfc-0189-Http_Service_Updates.pdf?raw=true
>
> Am 07.04.2014 um 11:20 schrieb Julian Sedding <js...@gmail.com>:
>
>> I agree with Bertrand. Generally, I'm in favor of supporting the Accept header.
>>
>> However coding an arbitrary logic into Sling Engine (or some other
>> core bundle) does not sound good to me.
>>
>> The benefits of a pluggable solution would be
>> - preservation of modularity and
>> - the implementation of some "special" logic could live in a "contrib"
>> bundle, where it's easier to drop support, if the idea turns out to be
>> not so good.
>> - other headers, e.g. Accept-Language, could also be easily supported.
>>
>> Regards
>> Julian
>>
>>
>> On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
>> <bd...@apache.org> wrote:
>>> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger <fm...@adobe.com> wrote:
>>>> ...I would prefer to not go over board, at least not initially, and keep it simple and covering simple use cases....
>>>
>>> I like simple but what I object to is burning this into the Sling core
>>> - what you suggest is based on somewhat arbitrary rules (single
>>> content-type etc) which I don't feel good burning into the core. An
>>> extension point for setting selectors + extensions is not rocket
>>> science.
>>>
>>> -Bertrand
>
Re: Support REST-ful APIs
Posted by Felix Meschberger <fm...@adobe.com>.
Hi Tyson
Am 11.04.2014 um 00:35 schrieb Tyson Norris <tn...@adobe.com>:
> along the lines of supporting REST-ful APIs, is there any way (mapping? etc) to support an api like :
> GET /api/v1/foo/bar
First and foremost: don't do the v1 thing since it is just wrong. An URL addresses a resource and an address never contains a version. Using version identifiers in so-called REST-ful HTTP APIs seems to be urban legend.
>
> where:
> - /api and /v1 are obviously not content paths
> - foo and bar are not sling resources, but might be treated as synthetic resources if that is required
> - we cannot use Accept header (is it possible to use .json as a default extension?)
With my proposal you can (and should) use the Accept header instead of extensions. In fact, my proposal supports extension-less Accept header based support as well as browser-supported extensions without Accept header.
As for the mount point: I would think a ResourceProvider would do the trick. You can root it at your API mount point and you can treat the path however you like and map it to resources (regardless of whether they are virtual or real). And you can even expose the template tokens as ResourceMetadata.
Regards
Felix
>
> we are in the process of defining some apis that exist alongside other platforms that use apis in this common url format, and it would be really nice to use something like jaxrs style tokens for paths that are not sling resource, but yet desired to be exposed as urls (I know, this is not the way of sling in general…) e.g. @Path("/users/{username}”)
>
> Side note: I haven’t looks into the sling jaxrs support added via https://issues.apache.org/jira/browse/SLING-2192, but plan to try it out - does it support path tokens/wildcards?
>
> Thanks for any ideas.
> Tyson
>
>
> On Apr 7, 2014, at 5:33 PM, Alexander Klimetschek <ak...@adobe.com>> wrote:
>
> Proposal sounds good to me. I would agree to move this to a plugin that gets the accept header (is there anything else?) and can update any existing selectors/extension/suffix (the PathInfo) parsed already.
>
> void updatePathInfo(String[] accepts, PathInfo pathInfo);
>
> Notes:
> - accept header already parsed (might need to be a special object to include weights)
> - PathInfo is basically a RequestPathInfo with setters
>
> While the default would not do anything if something was taken from the URL, this might still be useful once you support accept headers this way, and applications could extend that behaviour. Or simply turn it off (as it is now).
>
> Cheers,
> Alex
>
>
> On 07.04.2014, at 13:39, Julian Reschke <ju...@gmx.de>> wrote:
>
> On 2014-04-07 15:59, Felix Meschberger wrote:
> Hi
>
> Ok, it is not exactly arbitrary logic. Turns out that content types of the style
>
> application/someformat+somesyntax
>
> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I expect some application on the other (client) side and this will in general not come with a list of content types but with a single one asking for a concrete representation.
> ...
>
> The "structured syntax" is defined in <http://tools.ietf.org/html/rfc6839> -- note that you can't simply make up these suffixes (nor media types...).
>
> Best regards, Julian
>
>
>
Re: Support REST-ful APIs
Posted by Ian Boston <ie...@tfd.co.uk>.
On Friday, April 11, 2014, Tyson Norris <tn...@adobe.com> wrote:
>
>
> > On Apr 10, 2014, at 11:26 PM, "Ian Boston" <ieb@tfd.co.uk <javascript:;>>
> wrote:
> >
> > Hi,
> > This style of REST is supported. There are 2 options, probably more,
> > assuming that you have written your Api implementing using servlets.
> Mount
> > the servlets at a hard coded path using the sling servlet annotation, but
> > this won't allow you to acl the end point, or give the Api a resource
> type,
> > and create some nodes to mount it at the desired path. Don't think of the
> > path as content, think of it as a mount point form your Api. The
> advantage
> > of the latter is it becomes easy to remount and acl.
> >
>
> I'm not sure how hard coding the paths allows for multiple urls can be
> served on the same servlet using the path annotation (without using
> selectors etc)?
>
> My example was misleading where:
> /api/v1/foo/bar
> Should be more like:
> /api/v1/foo/{var}
> Where {var} is some variable/id that does not easily map to a resource.
>
> Which is why I wonder whether resource provider would be better suited to
> handle this case than a servlet?
What would happen if the servlet was mounted at /api/v1/foo ? I think /bar
would appear in path info, as iirc the resource resolver finds the first
existing resource.
Have you tried that?
Ian
>
> Thanks
> Tyson
>
> > You can also mount jaxrs as a osgi servlet, but the processing model of
> > implementations like RESTEasy is incompatible with sling. If you do that,
> > you are on your own as far as the resource resolver.
> >
> > Best regards
> > Ian
> >
> > Sent from my ipad, sorry for the typos.
> >
> >> On Thursday, April 10, 2014, Tyson Norris <tnorris@adobe.com<javascript:;>>
> wrote:
> >>
> >> along the lines of supporting REST-ful APIs, is there any way (mapping?
> >> etc) to support an api like :
> >> GET /api/v1/foo/bar
> >>
> >> where:
> >> - /api and /v1 are obviously not content paths
> >> - foo and bar are not sling resources, but might be treated as synthetic
> >> resources if that is required
> >> - we cannot use Accept header (is it possible to use .json as a default
> >> extension?)
> >>
> >> we are in the process of defining some apis that exist alongside other
> >> platforms that use apis in this common url format, and it would be
> really
> >> nice to use something like jaxrs style tokens for paths that are not
> sling
> >> resource, but yet desired to be exposed as urls (I know, this is not the
> >> way of sling in general...) e.g. @Path("/users/{username}")
> >>
> >> Side note: I haven't looks into the sling jaxrs support added via
> >> https://issues.apache.org/jira/browse/SLING-2192, but plan to try it
> out
> >> - does it support path tokens/wildcards?
> >>
> >> Thanks for any ideas.
> >> Tyson
> >>
> >>
> >> On Apr 7, 2014, at 5:33 PM, Alexander Klimetschek <aklimets@adobet.com<javascript:;>
> <javascript:;>
> >> <mailto:aklimets@adobe.com <javascript:;> <javascript:;>>> wrote:
> >>
> >> Proposal sounds good to me. I would agree to move this to a plugin that
> >> gets the accept header (is there anything else?) and can update any
> >> existing selectors/extension/suffix (the PathInfo) parsed already.
> >>
> >> void updatePathInfo(String[] accepts, PathInfo pathInfo);
> >>
> >> Notes:
> >> - accept header already parsed (might need to be a special object to
> >> include weights)
> >> - PathInfo is basically a RequestPathInfo with setters
> >>
> >> While the default would not do anything if something was taken from the
> >> URL, this might still be useful once you support accept headers this
> way,
> >> and applications could extend that behaviour. Or simply turn it off (as
> it
> >> is now).
> >>
> >> Cheers,
> >> Alex
> >>
> >>
> >> On 07.04.2014, at 13:39, Julian Reschke <julian.reschke@gmx.de<javascript:;>
> <javascript:;>
> >> <mailto:julian.reschke@gmx.de <javascript:;> <javascript:;>>> wrote:
> >>
> >> On 2014-04-07 15:59, Felix Meschberger wrote:
> >> Hi
> >>
> >> Ok, it is not exactly arbitrary logic. Turns out that content types of
> the
> >> style
> >>
> >> application/someformat+somesyntax
> >>
> >> are pretty common (see [1], [2]). Also when talking about REST-ful APIs
> I
> >> expect some application on the other (client) side and this will in
> general
> >> not come with a list of content types but with a single one asking for a
> >> concrete representation.
> >> ...
> >>
> >> The "structured syntax" is defined in <
> http://tools.ietf.org/html/rfc6839>
> >> -- note that you can't simply make up these suffixes (nor media
> types...).
> >>
> >> Best regards, Julian
> >>
> >>
> >>
> >>
>
Re: Support REST-ful APIs
Posted by Tyson Norris <tn...@adobe.com>.
> On Apr 10, 2014, at 11:26 PM, "Ian Boston" <ie...@tfd.co.uk> wrote:
>
> Hi,
> This style of REST is supported. There are 2 options, probably more,
> assuming that you have written your Api implementing using servlets. Mount
> the servlets at a hard coded path using the sling servlet annotation, but
> this won't allow you to acl the end point, or give the Api a resource type,
> and create some nodes to mount it at the desired path. Don't think of the
> path as content, think of it as a mount point form your Api. The advantage
> of the latter is it becomes easy to remount and acl.
>
I'm not sure how hard coding the paths allows for multiple urls can be served on the same servlet using the path annotation (without using selectors etc)?
My example was misleading where:
/api/v1/foo/bar
Should be more like:
/api/v1/foo/{var}
Where {var} is some variable/id that does not easily map to a resource.
Which is why I wonder whether resource provider would be better suited to handle this case than a servlet?
Thanks
Tyson
> You can also mount jaxrs as a osgi servlet, but the processing model of
> implementations like RESTEasy is incompatible with sling. If you do that,
> you are on your own as far as the resource resolver.
>
> Best regards
> Ian
>
> Sent from my ipad, sorry for the typos.
>
>> On Thursday, April 10, 2014, Tyson Norris <tn...@adobe.com> wrote:
>>
>> along the lines of supporting REST-ful APIs, is there any way (mapping?
>> etc) to support an api like :
>> GET /api/v1/foo/bar
>>
>> where:
>> - /api and /v1 are obviously not content paths
>> - foo and bar are not sling resources, but might be treated as synthetic
>> resources if that is required
>> - we cannot use Accept header (is it possible to use .json as a default
>> extension?)
>>
>> we are in the process of defining some apis that exist alongside other
>> platforms that use apis in this common url format, and it would be really
>> nice to use something like jaxrs style tokens for paths that are not sling
>> resource, but yet desired to be exposed as urls (I know, this is not the
>> way of sling in general...) e.g. @Path("/users/{username}")
>>
>> Side note: I haven't looks into the sling jaxrs support added via
>> https://issues.apache.org/jira/browse/SLING-2192, but plan to try it out
>> - does it support path tokens/wildcards?
>>
>> Thanks for any ideas.
>> Tyson
>>
>>
>> On Apr 7, 2014, at 5:33 PM, Alexander Klimetschek <aklimets@adobet.com<javascript:;>
>> <mailto:aklimets@adobe.com <javascript:;>>> wrote:
>>
>> Proposal sounds good to me. I would agree to move this to a plugin that
>> gets the accept header (is there anything else?) and can update any
>> existing selectors/extension/suffix (the PathInfo) parsed already.
>>
>> void updatePathInfo(String[] accepts, PathInfo pathInfo);
>>
>> Notes:
>> - accept header already parsed (might need to be a special object to
>> include weights)
>> - PathInfo is basically a RequestPathInfo with setters
>>
>> While the default would not do anything if something was taken from the
>> URL, this might still be useful once you support accept headers this way,
>> and applications could extend that behaviour. Or simply turn it off (as it
>> is now).
>>
>> Cheers,
>> Alex
>>
>>
>> On 07.04.2014, at 13:39, Julian Reschke <julian.reschke@gmx.de<javascript:;>
>> <mailto:julian.reschke@gmx.de <javascript:;>>> wrote:
>>
>> On 2014-04-07 15:59, Felix Meschberger wrote:
>> Hi
>>
>> Ok, it is not exactly arbitrary logic. Turns out that content types of the
>> style
>>
>> application/someformat+somesyntax
>>
>> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I
>> expect some application on the other (client) side and this will in general
>> not come with a list of content types but with a single one asking for a
>> concrete representation.
>> ...
>>
>> The "structured syntax" is defined in <http://tools.ietf.org/html/rfc6839>
>> -- note that you can't simply make up these suffixes (nor media types...).
>>
>> Best regards, Julian
>>
>>
>>
>>
Re: Support REST-ful APIs
Posted by Ian Boston <ie...@tfd.co.uk>.
Hi,
This style of REST is supported. There are 2 options, probably more,
assuming that you have written your Api implementing using servlets. Mount
the servlets at a hard coded path using the sling servlet annotation, but
this won't allow you to acl the end point, or give the Api a resource type,
and create some nodes to mount it at the desired path. Don't think of the
path as content, think of it as a mount point form your Api. The advantage
of the latter is it becomes easy to remount and acl.
You can also mount jaxrs as a osgi servlet, but the processing model of
implementations like RESTEasy is incompatible with sling. If you do that,
you are on your own as far as the resource resolver.
Best regards
Ian
Sent from my ipad, sorry for the typos.
On Thursday, April 10, 2014, Tyson Norris <tn...@adobe.com> wrote:
> along the lines of supporting REST-ful APIs, is there any way (mapping?
> etc) to support an api like :
> GET /api/v1/foo/bar
>
> where:
> - /api and /v1 are obviously not content paths
> - foo and bar are not sling resources, but might be treated as synthetic
> resources if that is required
> - we cannot use Accept header (is it possible to use .json as a default
> extension?)
>
> we are in the process of defining some apis that exist alongside other
> platforms that use apis in this common url format, and it would be really
> nice to use something like jaxrs style tokens for paths that are not sling
> resource, but yet desired to be exposed as urls (I know, this is not the
> way of sling in general...) e.g. @Path("/users/{username}")
>
> Side note: I haven't looks into the sling jaxrs support added via
> https://issues.apache.org/jira/browse/SLING-2192, but plan to try it out
> - does it support path tokens/wildcards?
>
> Thanks for any ideas.
> Tyson
>
>
> On Apr 7, 2014, at 5:33 PM, Alexander Klimetschek <aklimets@adobet.com<javascript:;>
> <mailto:aklimets@adobe.com <javascript:;>>> wrote:
>
> Proposal sounds good to me. I would agree to move this to a plugin that
> gets the accept header (is there anything else?) and can update any
> existing selectors/extension/suffix (the PathInfo) parsed already.
>
> void updatePathInfo(String[] accepts, PathInfo pathInfo);
>
> Notes:
> - accept header already parsed (might need to be a special object to
> include weights)
> - PathInfo is basically a RequestPathInfo with setters
>
> While the default would not do anything if something was taken from the
> URL, this might still be useful once you support accept headers this way,
> and applications could extend that behaviour. Or simply turn it off (as it
> is now).
>
> Cheers,
> Alex
>
>
> On 07.04.2014, at 13:39, Julian Reschke <julian.reschke@gmx.de<javascript:;>
> <mailto:julian.reschke@gmx.de <javascript:;>>> wrote:
>
> On 2014-04-07 15:59, Felix Meschberger wrote:
> Hi
>
> Ok, it is not exactly arbitrary logic. Turns out that content types of the
> style
>
> application/someformat+somesyntax
>
> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I
> expect some application on the other (client) side and this will in general
> not come with a list of content types but with a single one asking for a
> concrete representation.
> ...
>
> The "structured syntax" is defined in <http://tools.ietf.org/html/rfc6839>
> -- note that you can't simply make up these suffixes (nor media types...).
>
> Best regards, Julian
>
>
>
>
Re: Support REST-ful APIs
Posted by Tyson Norris <tn...@adobe.com>.
along the lines of supporting REST-ful APIs, is there any way (mapping? etc) to support an api like :
GET /api/v1/foo/bar
where:
- /api and /v1 are obviously not content paths
- foo and bar are not sling resources, but might be treated as synthetic resources if that is required
- we cannot use Accept header (is it possible to use .json as a default extension?)
we are in the process of defining some apis that exist alongside other platforms that use apis in this common url format, and it would be really nice to use something like jaxrs style tokens for paths that are not sling resource, but yet desired to be exposed as urls (I know, this is not the way of sling in general…) e.g. @Path("/users/{username}”)
Side note: I haven’t looks into the sling jaxrs support added via https://issues.apache.org/jira/browse/SLING-2192, but plan to try it out - does it support path tokens/wildcards?
Thanks for any ideas.
Tyson
On Apr 7, 2014, at 5:33 PM, Alexander Klimetschek <ak...@adobe.com>> wrote:
Proposal sounds good to me. I would agree to move this to a plugin that gets the accept header (is there anything else?) and can update any existing selectors/extension/suffix (the PathInfo) parsed already.
void updatePathInfo(String[] accepts, PathInfo pathInfo);
Notes:
- accept header already parsed (might need to be a special object to include weights)
- PathInfo is basically a RequestPathInfo with setters
While the default would not do anything if something was taken from the URL, this might still be useful once you support accept headers this way, and applications could extend that behaviour. Or simply turn it off (as it is now).
Cheers,
Alex
On 07.04.2014, at 13:39, Julian Reschke <ju...@gmx.de>> wrote:
On 2014-04-07 15:59, Felix Meschberger wrote:
Hi
Ok, it is not exactly arbitrary logic. Turns out that content types of the style
application/someformat+somesyntax
are pretty common (see [1], [2]). Also when talking about REST-ful APIs I expect some application on the other (client) side and this will in general not come with a list of content types but with a single one asking for a concrete representation.
...
The "structured syntax" is defined in <http://tools.ietf.org/html/rfc6839> -- note that you can't simply make up these suffixes (nor media types...).
Best regards, Julian
Re: Support REST-ful APIs
Posted by Alexander Klimetschek <ak...@adobe.com>.
Proposal sounds good to me. I would agree to move this to a plugin that gets the accept header (is there anything else?) and can update any existing selectors/extension/suffix (the PathInfo) parsed already.
void updatePathInfo(String[] accepts, PathInfo pathInfo);
Notes:
- accept header already parsed (might need to be a special object to include weights)
- PathInfo is basically a RequestPathInfo with setters
While the default would not do anything if something was taken from the URL, this might still be useful once you support accept headers this way, and applications could extend that behaviour. Or simply turn it off (as it is now).
Cheers,
Alex
On 07.04.2014, at 13:39, Julian Reschke <ju...@gmx.de> wrote:
> On 2014-04-07 15:59, Felix Meschberger wrote:
>> Hi
>>
>> Ok, it is not exactly arbitrary logic. Turns out that content types of the style
>>
>>> application/someformat+somesyntax
>>
>> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I expect some application on the other (client) side and this will in general not come with a list of content types but with a single one asking for a concrete representation.
>> ...
>
> The "structured syntax" is defined in <http://tools.ietf.org/html/rfc6839> -- note that you can't simply make up these suffixes (nor media types...).
>
> Best regards, Julian
>
Re: Support REST-ful APIs
Posted by Julian Reschke <ju...@gmx.de>.
On 2014-04-07 15:59, Felix Meschberger wrote:
> Hi
>
> Ok, it is not exactly arbitrary logic. Turns out that content types of the style
>
>> application/someformat+somesyntax
>
> are pretty common (see [1], [2]). Also when talking about REST-ful APIs I expect some application on the other (client) side and this will in general not come with a list of content types but with a single one asking for a concrete representation.
> ...
The "structured syntax" is defined in
<http://tools.ietf.org/html/rfc6839> -- note that you can't simply make
up these suffixes (nor media types...).
Best regards, Julian
Re: Support REST-ful APIs
Posted by Felix Meschberger <fm...@adobe.com>.
Hi
Ok, it is not exactly arbitrary logic. Turns out that content types of the style
> application/someformat+somesyntax
are pretty common (see [1], [2]). Also when talking about REST-ful APIs I expect some application on the other (client) side and this will in general not come with a list of content types but with a single one asking for a concrete representation.
To have a plugin, you need to define and export an API and you have to take care about backwards compatibility and evolution. I don't exactly see where such a travel would lead to right now.
As to other headers: This is about content type negotiation which involves as per the HTTP spec the Accept header. The Accept-Language header is for the language to be used for the representation of the resource but does not have an influence on the content type.
Regards
Felix
[1] http://www.iana.org/assignments/media-types/media-types.xhtml
[2] https://github.com/osgi/design/blob/master/rfcs/rfc0189/rfc-0189-Http_Service_Updates.pdf?raw=true
Am 07.04.2014 um 11:20 schrieb Julian Sedding <js...@gmail.com>:
> I agree with Bertrand. Generally, I'm in favor of supporting the Accept header.
>
> However coding an arbitrary logic into Sling Engine (or some other
> core bundle) does not sound good to me.
>
> The benefits of a pluggable solution would be
> - preservation of modularity and
> - the implementation of some "special" logic could live in a "contrib"
> bundle, where it's easier to drop support, if the idea turns out to be
> not so good.
> - other headers, e.g. Accept-Language, could also be easily supported.
>
> Regards
> Julian
>
>
> On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
> <bd...@apache.org> wrote:
>> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger <fm...@adobe.com> wrote:
>>> ...I would prefer to not go over board, at least not initially, and keep it simple and covering simple use cases....
>>
>> I like simple but what I object to is burning this into the Sling core
>> - what you suggest is based on somewhat arbitrary rules (single
>> content-type etc) which I don't feel good burning into the core. An
>> extension point for setting selectors + extensions is not rocket
>> science.
>>
>> -Bertrand
Re: Support REST-ful APIs
Posted by Julian Sedding <js...@gmail.com>.
I agree with Bertrand. Generally, I'm in favor of supporting the Accept header.
However coding an arbitrary logic into Sling Engine (or some other
core bundle) does not sound good to me.
The benefits of a pluggable solution would be
- preservation of modularity and
- the implementation of some "special" logic could live in a "contrib"
bundle, where it's easier to drop support, if the idea turns out to be
not so good.
- other headers, e.g. Accept-Language, could also be easily supported.
Regards
Julian
On Mon, Apr 7, 2014 at 10:13 AM, Bertrand Delacretaz
<bd...@apache.org> wrote:
> On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger <fm...@adobe.com> wrote:
>> ...I would prefer to not go over board, at least not initially, and keep it simple and covering simple use cases....
>
> I like simple but what I object to is burning this into the Sling core
> - what you suggest is based on somewhat arbitrary rules (single
> content-type etc) which I don't feel good burning into the core. An
> extension point for setting selectors + extensions is not rocket
> science.
>
> -Bertrand
Re: Support REST-ful APIs
Posted by Bertrand Delacretaz <bd...@apache.org>.
On Mon, Apr 7, 2014 at 9:58 AM, Felix Meschberger <fm...@adobe.com> wrote:
> ...I would prefer to not go over board, at least not initially, and keep it simple and covering simple use cases....
I like simple but what I object to is burning this into the Sling core
- what you suggest is based on somewhat arbitrary rules (single
content-type etc) which I don't feel good burning into the core. An
extension point for setting selectors + extensions is not rocket
science.
-Bertrand
Re: Support REST-ful APIs
Posted by Felix Meschberger <fm...@adobe.com>.
Hi
Am 07.04.2014 um 09:42 schrieb Bertrand Delacretaz <bd...@apache.org>:
> Hi,
>
> On Mon, Apr 7, 2014 at 9:24 AM, Felix Meschberger <fm...@adobe.com> 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"...
>
> I like the idea, but only if there are no extensions nor selectors in
> the current request, otherwise it's confusing.
See the conditions I listed at the end of my proposal :-)
>
>> ... 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)...
>
> I'd rather leave the decision to a plugin that the
> SlingRequestPathInfo constructor calls only if there is no extension
> and no selectors. The plugin gets the request object and can return
> extension + selectors.
I would prefer to not go over board, at least not initially, and keep it simple and covering simple use cases.
Regards
Felix
>
> We can then implement something like you suggest, that users can
> replace that with their own algorithms if needed.
>
>> ...Only if Accept header has a single content type...
>
> Might be fine for your use cases, but using a plugin also allows for
> more sophisticated content negociation.
>
> -Bertrand
Re: Support REST-ful APIs
Posted by Bertrand Delacretaz <bd...@apache.org>.
Hi,
On Mon, Apr 7, 2014 at 9:24 AM, Felix Meschberger <fm...@adobe.com> 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"...
I like the idea, but only if there are no extensions nor selectors in
the current request, otherwise it's confusing.
>... 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)...
I'd rather leave the decision to a plugin that the
SlingRequestPathInfo constructor calls only if there is no extension
and no selectors. The plugin gets the request object and can return
extension + selectors.
We can then implement something like you suggest, that users can
replace that with their own algorithms if needed.
> ...Only if Accept header has a single content type...
Might be fine for your use cases, but using a plugin also allows for
more sophisticated content negociation.
-Bertrand
Re: Support REST-ful APIs
Posted by Felix Meschberger <fm...@adobe.com>.
Hi
Am 14.04.2014 um 10:52 schrieb Alexander Klimetschek <ak...@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 <fi...@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/>
>>
>
Re: Support REST-ful APIs
Posted by Robert Munteanu <ro...@lmn.ro>.
On Mon, Apr 14, 2014 at 8:52 PM, Alexander Klimetschek
<ak...@adobe.com> wrote:
> Thanks Roy for clarifying things.
>
> 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"
> - and maybe it's a good idea to use a redirect to /content/foo.json instead of rendering it right away
>
> 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 think we should, for consistency with the plain example above.
> - 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 think we should send a 406 not acceptable response here, since we
can't be sure what the client intended.
Robert
>
> With suffix it gets even more tricky, as it comes after and thus requires the extension in the URL:
> - /content/foo.json/mysuffix
> - 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.
>
> 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 <fi...@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/>
>>
>
--
Sent from my (old) computer
Re: Support REST-ful APIs
Posted by Alexander Klimetschek <ak...@adobe.com>.
Thanks Roy for clarifying things.
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"
- and maybe it's a good idea to use a redirect to /content/foo.json instead of rendering it right away
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?
- or should we allow negotiation on the final URL /content/foo.two.json with accept = text/html would redirect to /content/foo.two.html ?
With suffix it gets even more tricky, as it comes after and thus requires the extension in the URL:
- /content/foo.json/mysuffix
- 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.
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 <fi...@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/>
>
Re: Support REST-ful APIs
Posted by Felix Meschberger <fm...@adobe.com>.
Hi
Thanks for insights. Very helpful !
Am 13.04.2014 um 23:24 schrieb Roy T. Fielding <fi...@gbiv.com>:
> 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.
Absolutely
>
> 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.
Maybe "impure" is the wrong word for it (and as a native german speaker I can always flee into the incomplete language skills hideout ;-) ).
I am under the impression that from a purity perspective the URL /teams/fcbasel is cleaner than /teams/fcbasel.html. Since these are two distinct URLs and hence technically two distinct resources. While in Sling both URLs actually refer to the same resource, whether the latter .html URL actually implies representation/content negotiation (well not exactly negotiation, though, its rather requesting a specific representation, HTML namely).
>
>> 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.
Ok, cool. This basically says, Sling does it right: Good to hear ;-)
>
> In general, x- is not an appropriate prefix for media types.
> Sling should not encourage their use.
Sure, thanks. Having read a few more lines of RFCs, namely RFC 6838, I would think this should be stipulating the Vendor tree, Personal tree or even the unregistered tree.
>
>> 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.
That is an interesting, yet excellent argument.
So considering all the discussions on this thread, I think my proposal can just be dropped and consider, the way how Sling handles URLs is really adequate and there is no more things we should really do at this time.
Regards
Felix
>
> 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/>
>
Re: Support REST-ful APIs
Posted by "Roy T. Fielding" <fi...@gbiv.com>.
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/>