Feature Proposal: Enhanced REST Support
Motivation
The current REST support has three major shortcommings:
- It is quite restrictive in what it allows, with its
/rest/PluginName/handler
URL syntax. It is more RPC-like than RESTful
- The semantic is only defined for GET/POST operations which are handled the same way by the
rest
script.
- Authentication/Authorization is required if the
rest
script is protected, even if the handler does not require authorization.
Description and Documentation
- To allow the extensions to provide a rich set of URLs, the
registerRESTHandler
function could be modified/enhanced/overloaded to receive a URL pattern instead the name of the handler. To solve ambiguities, the first pattern that matches the URL will process it.
-
REST handlers could be declared to be GET, POST or DELETE operations. If the wrong HTTP action is used to invoke a REST handler, an error should be returned.
-
REST should declare if they need authentication/authorization or not. REST calls that require auth but are not provided with it (either in the form of basic auth in the request or by virtue of a cookied login) should be 401'd.
- We have completed the first part of this; the discussion about status code is long, and can be found below, but is converging on 401 + WWW-Authenticate: loginurl=URL -- CrawfordCurrie
- REST should handle correct charset encoding/decoding. REST requests are always utf8 encoded. The current foswiki response code does not distinguish xhr calls from normal ones and does not take care of properly converting parameters.
- Make it easier / establish standards by which Foswiki can recognise a request raised by XMLHttpRequest (which always encodes in utf8). Use of the
X-Requested-With
header seems to be a commonly adopted approach.
Examples
(syntax subject to change, GET,POST,DELETE, REQUIRE_AUTH, NO_AUTH should be constants somewhere)
Alternatives: (Both are meant to register a handler for URL that match the given pattern, that works only on GET and requires authentication.)
-
registerRESTHandler("/pages/(.*)",&listWikiTopicForWeb,GET,REQUIRE_AUTH);
-
registerRESTHandler("/pages/(.*)",&listWikiTopicForWeb,{ method=> GET, require_auth=>1});
NOTE: this is pretty much what
RestPlugin was written to address.
Impact
Implementation
--
Contributors: RafaelAlvarez - 17 Apr 2009
Discussion
There needs to be a way for a REST handler registration to declare whether it needs an authorised user or not. In the template login case, this is simple enough to deal with, but in the apache login case, it may require a redirect. REST calls that require auth but are not provided with it (either in the form of basic auth in the request or by virtue of a cookied login) should be 401'd.
--
CrawfordCurrie - 18 Apr 2009
yes, it'd be nice to have foswiki's 'rest' handler to actually implement
REST
, and be resource oriented, obey the requested media types and so on
right now, its more of an rpc like thing, and its important not to rush adding another not quite integrated thing - the example above (list of topics) for eg should be done using the appropriate TOM syntax (for which i'm working on result sets), and the results then should be returned in json/xml/text etc using the requested media type..
--
SvenDowideit - 18 Apr 2009
Sometimes I want to POST something that is not Topic related, thus the
rest
mechanism should not be tied to
TOM
. But once the
REST
mechanism is in place, a
TOMPlugin
could be created to handle TOM-related
REST
operations. (I'm a fan of microkernels).
As for the "requested media type" part, if you want it to be really "generic", meaning that the same URL can return different representations of the same data, then we need to define a contract with the
REST
handlers: they should return something that could be marshalled, and it would be the
rest
script that would marshall the answer to JSON/XML or text.
--
RafaelAlvarez - 18 Apr 2009 I'd go further with the params...
-
registerRESTHandler({url => "/pages/(.*)", function => &listWikiTopicForWeb, method=> GET, require_auth=>1});
Though I wonder what URL endpoint that gets us if someone wants to make clashes..
-
registerRESTHandler({url => "/search/(.*)", function => &Foswiki::UI::Search, method=> GET, require_auth=>1});
and it re-inforces my desire that
GET
gives us a read only store.
--
SvenDowideit - 19 Apr 2009
When {AuthScripts} is checked, it works by raising an
AccessControlException that is caught in
UI.pm
and processed by asking the login manager if it wants to force authentication; in effect, it passes responsibility for the response on to the login manager. In the case of the template login manager it is handled by the generation of a login page with a 200 status response. This is appropriate for most scripts, but for
rest
it's a FAIL. This is because REST is used for AJAX, which requires that
rest
respond with a status code that can be processed in the client, not a 200 with a login page.
--
CrawfordCurrie - 31 Jan 2012
See
Use401ForCookieAuth for the discussion on this issue, concluding with.....
I think we all just agreed to adopt HTTP 401 for
all auth, not just REST - and in the process to remove the redirect to the /bin/login script.
Crawford, please extract this feature-ette from this REST specific one - and you can consider it accepted, as its really a continuation of the
400 status
task we worked on last year.
--
SvenDowideit - 09 Feb 2012
Parking this. No developer. And pieces have already been done here an there, so it probably needs rework.
--
GeorgeClark - 13 Feb 2016