Search code examples
authenticationurl-routingrestletrestlet-2.0

Restelet routing: some resources require authentication, some don't. How to do it?


I've been workin on a RESTlet 2.1 project. I've figured out how to set up authentication for my Resources. Fact is.. not all of them need authentication! I am quite puzzled about how should I do it right.

In the following code you can see the outline of my server Application, in particular the "create Inbound Root":

@Override
public Restlet createInboundRoot(){

    /* the structure so far is: a filter, followed by an authenticator,
       followed by a rooter. 
       The filter is returned at end of the method.
    */


    //Init filter:
    SomeFilter someFilter = new SomeFilter();


            //Init authenticator:
    ChallengeAuthenticator authenticator = new ChallengeAuthenticator(
        ......);
    //more authenticator stuff goes here....        


    //Init router:
    Router router = new Router(getContext());
    //this should be a public resource, no need for auth:
    router.attach("/0.1/getResource", SomeResource.class)
    //this is a private resource, needs auth:
    router.attach("/0.1/getPrivateResource", PrivateResource.class);

    //set up the flow: filter -> authenticator -> router
    authenticator.setNext(router);      
    someFilter.setNext(authenticator);
    return someFilter;

}

The filter must be before everything, since I need to modify some Headers for all packages. After the filter I would like to set-up a fork, where requests of my public resource are just routed to the Resource class and requests of the private resource must pass through the authenticator.

How can I accomplish this? I am new to this framework and couldn't figure out even if it looks dead simple.


Solution

  • I've figured out the full solution to this, it was about "URI templates". The one thing missing was the different way a router can match the uri, in fact, the problem needed a "Match the first part of the URI" kind of approach.

        /*
         * Routing structure:
         * 
         *                            ---/public---->(publicR()----> Public Resources
         * (Filter()---->(routerPP()--|
         *                            ---/private--->(authenticator()---->(privateR()---> Private Resources
         *       
         */
    

    where routerPP takes the decision if the URL begins with /public or /private:

        Router routerPP = new Router(getContext());
        routerPP.setDefaultMatchingMode(Template.MODE_STARTS_WITH);
        routerPP.attach("/private", authenticator);
        routerPP.attach("/public", publicR);
    

    the one particularity is that, after an URL "passes through" a router, it looses the matched part of the URL, therefore a following router (e.g. the public one) will have this structure:

        Router publicR = new Router(getContext());
        publicR.attach("/somePublicResource", SomePublicResource.class);
    

    and such configuration matches the following URL: http://somehost.com/public/somePublicResource

    if in the second router you add the "/public/" token again, you will get a "resource not found" error, and the resource would then be on: http://somehost.com/public/public/somePublicResource

    So the routers match and remove from the URL.

    Reference about the routing and the URI matching I've found useful are:

    http://restlet-discuss.1400322.n2.nabble.com/Trying-to-route-to-two-routes-that-start-with-same-prefix-td7019794.html

    http://restlet.org/learn/javadocs/snapshot/jse/api/org/restlet/routing/Router.html