java - Restlet conditional routing to different resources -
i have post
request assign different resources
depending on body content.
if body contains non empty token: "token":"1q2w3e4r5t"
rout request tokenedresource,
otherwise rout nontokenresource
.
i thought using filter (@beforehandle
) it, indication filter returns continue
or stop
...
any suggestions?
to need extend restlet routing. latter responsible determine route matches particular request basing on computed score.
in particular routing involves 2 classes need override: router
, templateroute
. router 1 responsible of creation of template route. if want provide custom template route, need provide custom router. within custom template route, implement own algorithm regarding route score.
here implementation of custom router:
public class customrouter extends internalrouter { public customrouter(context context) { super(context); setfinderclass(customfinder.class); } protected templateroute createroute(string uripattern, restlet target, int matchingmode) { customtemplateroute result = new customtemplateroute( this, uripattern, target); result.gettemplate().setmatchingmode(matchingmode); result.setmatchingquery(getdefaultmatchingquery()); return result; } }
what isn't obvious understand why need specify custom finder using method setfinderclass
. finder in restlet responsible of instantiating example server resource each request. problem default implementation (the class finder
) can't have access associated class (targetclass
). if need know (which seems case), must provide own implementation. we'll focus on later.
with class, here way attach server resource within application class:
@override public restlet createinboundroot() { router router = new customrouter(getcontext()); router.attach("/test", tokenedresource.class); router.attach("/test", nontokenresource.class); return router; }
we must attach them on same path.
here implementation of custom template route:
public class customtemplateroute extends templateroute { public customtemplateroute(restlet next) { super(next); } public customtemplateroute(router router, string uritemplate, restlet next) { super(router, uritemplate, next); } public customtemplateroute(router router, template template, restlet next) { super(router, template, next); } @override public float score(request request, response response) { float result = super.score(request, response); (...) return result; } }
within method score
, increase score if in case of tokened request class tokenedresource
, decrease otherwise. allows let restlet select right server resource right case.
before going further, let provide content of class customfinder:
public class customfinder extends finder { private class<? extends serverresource> targetclass; public customfinder() { super(); } public customfinder(context context) { super(context); } public customfinder(context context, class<? extends serverresource> targetclass) { super(context, targetclass); this.targetclass = targetclass; } }
here way implement custom processing compute score:
@override public float score(request request, response response) { float result = super.score(request, response); if (istokenedserverresource()) { boolean containstoken = containstoken(request); if (containstoken) { return result + 0.1f; } else { return result - 0.1f; } } return result; }
the method istokenedserverresource
checks if server resource associated route (if any) class tokenedresource
. in case, have @ payload see if contains token method containstoken
.
here sample content method istokenedserverresource
:
private boolean istokenedserverresource() { if (getnext() instanceof customfinder) { customfinder finder = (customfinder) getnext(); if (myserverresource1.class.isassignablefrom(finder.gettargetclass())) { return true; } } return false; }
here sample content method containstoken
. supposes json content used , use jackson parse it.
private boolean containstoken(request request) { try { representation repr = request.getentity(); string content = repr.gettext(); objectmapper objectmapper = new objectmapper(); map<string, object> jsoncontent = objectmapper.readvalue( content, map.class); stringrepresentation srepr = new stringrepresentation( content, repr.getmediatype()); request.setentity(srepr); if (jsoncontent.get("token") != null) { return true; } } catch (exception ex) { (...) } return false; }
an important thing note need set again request entity in request (we use here stringrepresentation
) because default entity content can read once.
hope helps you, thierry
Comments
Post a Comment