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

Core
edit

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
Topic revision: r27 - 13 Feb 2016, GeorgeClark
The copyright of the content on this website is held by the contributing authors, except where stated elsewhere. See Copyright Statement. Creative Commons License    Legal Imprint    Privacy Policy