RE: Re: Re: Re: Dynamic Redirector
I haven't dug into this code, but I suspect you aren't manipulating References properly. I advise printing out the intermediate steps of your Reference computation to see where it goes wrong. That's just it, I don't think it is even selecting my Redirector as the target for the endpoint, b/c it is not even calling getTargetRef due to the child endpoints. Is there something else on Redirector or in my attachment I should be overriding so that it stops trying to match once it resolves the parent? Also, the template argument to Redirector is ignored if you override getTargetRef. Hmm, that doesn't seem to be the case for me, since my code is almost an exact copy the parent class. --tim On Sat, Apr 27, 2013 at 6:03 PM, Grant gsingers at apache dot org wrote: I don't understand what you mean by the handling of the {rr} template. The approach I suggested, overriding getTargetRef, ignores the template argument entirely. In my old code, I had: URI = hardcoded URI to resource Redirector redir = new Redirector(router.getContext(), URI + {rr}, Redirector.MODE_SERVER_OUTBOUND); router.attach(, redir, Template.MODE_STARTS_WITH); So, when I pass in http://foo:port/a/b/c, it redirects to URI/a/b/c In my new code, I pass in the target template simply as {rr} and then iin the getTargetRef, I do: protected Reference getTargetRef(Request request, Response response) { URI serviceURI = serviceLocator.getServiceURI(service); //THIS looks up the location of the service // Create the template Template rt = new Template(this.targetTemplate); rt.setLogger(getLogger()); // Return the formatted target URI if (new Reference(this.targetTemplate).isRelative()) { // Be sure to keep the resource's base reference. //Reference baseRef = new Reference(serviceURI.uri); if (log.isInfoEnabled()) { log.info(dynRedir from {} to {}, request.getResourceRef(), serviceURI.uri); } String format = rt.format(request, response); try { return new Reference(new URI(serviceURI.uri.toString() + format)); } catch (URISyntaxException e) { log.error(Exception, e); throw new RuntimeException(e); } } return new Reference(rt.format(request, response)); } /// I attach my DynamicRedirector at, for example, /a. When I pass in http://foo:port/a/b/c;, I want it to select my DynamicRedirector due to the /a (I'm using STARTS_WITH mode) part and then redirect to the target by passing along b/c (i.e. the {rr} part) such that the new URL would be something like http://dynamicHost:port/b/c;, based on what my serviceLocator returns. Like I said, it works great if I'm just matching at /a, but it doesn't handle the /b/c part. AFAICT, the handle() methods in Restlet are continuing to resolve down to the last endpoint (i.e. b/c) even though it has a match at /a. I will see if I can work up a standalone test example to demonstrate it. -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054458 -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054489
Re: Re: Re: Re: Dynamic Redirector
On Sun, Apr 28, 2013 at 11:42 AM, Grant gsing...@apache.org wrote: I haven't dug into this code, but I suspect you aren't manipulating References properly. I advise printing out the intermediate steps of your Reference computation to see where it goes wrong. That's just it, I don't think it is even selecting my Redirector as the target for the endpoint, b/c it is not even calling getTargetRef due to the child endpoints. Is there something else on Redirector or in my attachment I should be overriding so that it stops trying to match once it resolves the parent? I don't know what you mean by parent or child endpoints. If getTargetRef isn't being called, it's because the routing is wrong. If you want the application or component to send *all* requests to the redirector, use attachDefault: router.attachDefault(new MyRedirector(getContext(), ... other args ...); Also, the template argument to Redirector is ignored if you override getTargetRef. Hmm, that doesn't seem to be the case for me, since my code is almost an exact copy the parent class. The point of overriding getTargetRef is to give you the freedom to determine the target in arbitrary ways, which can be independent of the template. Here's the code for Redirector: https://github.com/restlet/restlet-framework-java/blob/master/modules/org.restlet/src/org/restlet/routing/Redirector.java You can see that the template is only used in getTargetRef. Your overridden getTargetRef need not use that template. You can just do something like this: public class MyRedirector extends Redirector { final FunctionReference, Reference targetMapper; public MyRedirector(Context context, FunctionReference, Reference targetMapper, int mode) { super(context, ignored, mode); this.targetMapper = targetMapper; } protected Reference getTargetRef(Request request, Response response) { return targetMapper.apply(request.getOriginalRef()); } } I'm using Guava's Function type as a shorthand here, to illustrate how the template can be made irrelevant to the redirection logic, but you can obviously write this any way you want. --tim -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054490
RE: Re: Re: Re: Re: Dynamic Redirector
On Sun, Apr 28, 2013 at 11:42 AM, Grant gsingers at apache dot org wrote: I haven't dug into this code, but I suspect you aren't manipulating References properly. I advise printing out the intermediate steps of your Reference computation to see where it goes wrong. That's just it, I don't think it is even selecting my Redirector as the target for the endpoint, b/c it is not even calling getTargetRef due to the child endpoints. Is there something else on Redirector or in my attachment I should be overriding so that it stops trying to match once it resolves the parent? I don't know what you mean by parent or child endpoints. If getTargetRef isn't being called, it's because the routing is wrong. If you want the application or component to send *all* requests to the redirector, use attachDefault: router.attachDefault(new MyRedirector(getContext(), ... other args ...); Yes, this is my suspicion too. Here's what I mean by parent and child. I am attaching my DynRedirector at: http://foo:port/a I am, at run time, making a call to http://foo:port/a/b. Thus, /b is my child endpoint and /a is my parent endpoint (ie the one that _is_ the Redirector). Not sure if this is the right nomenclature for Restlet, so please correct me. I can see that the Restlet that owns the DynRedirector is getting selected, but then it is not able to find it's next route b/c /b was never officially attached since it is (in my mind) supposed to be handled by the {rr} part. I suspect my issue is in how I am handling the {rr} part when I am attaching the DynamicRedirector to the owning Restlet. -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054494
Re: Re: Re: Re: Re: Dynamic Redirector
On Sun, Apr 28, 2013 at 12:58 PM, Grant gsing...@apache.org wrote: I am attaching my DynRedirector at: http://foo:port/a What's the code for this? It could be a Component level routing: VirtualHost host = component.getDefaultHost(); host.attach(/a, new DynRedirector(... args ...)); or an Application level routing: host.attach(/a, new MyApplication()); ... // In MyApplication.createInboundRoot: router.attachDefault(new DynRedirector(... args ...)); If it doesn't fall into one of these two camps, it's a good bet that your problem lies there. I am, at run time, making a call to http://foo:port/a/b. Thus, /b is my child endpoint and /a is my parent endpoint (ie the one that _is_ the Redirector). Not sure if this is the right nomenclature for Restlet, so please correct me. I would have said that you want all requests for resources at URIs with a prefix of http://foo:port/a to be handled by an instance of DynRedirector. I can see that the Restlet that owns the DynRedirector is getting selected, but then it is not able to find it's next route b/c /b was never officially attached since it is (in my mind) supposed to be handled by the {rr} part. I suspect my issue is in how I am handling the {rr} part when I am attaching the DynamicRedirector to the owning Restlet. Again, if DynRedirector.getTargetRef isn't being called at all, then the template argument passed to DynRedirector isn't being used, so handled by the {rr} part doesn't mean anything. I think you're confusing the path provided to attach, which can be a template pattern, with the template pattern passed to the Redirector. The former is used during routing, the latter is made available to getTargetRef to be used in determining a target reference from values in the current request and response. --tim -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054497
RE: Re: Dynamic Redirector
Hmm, digging in on this a bit more, I'm not sure it fully works for what I'm trying to do. The issue seems to be in the handling of the {rr} template. In other words, if I'm just redirecting a single URI to another (i.e. http://foo/a to http://bar/b), this approach works, but if I want to redirect all children URIs to the respective children URIs of the target. That is, if I have I request http://foo:port/a/b/c and I want to attach at http://foo:port/a and redirect to http://bar:port/b/c (by rewriting the target reference), it doesn't seem to work if I create a MyRedirector (my derivation of Redirector) that has an attach point of http://foo:port/a and a target template of {rr} whereas before in my static redirector I was doing http://bar:port/{rr} and everything was good. Thanks, Grant -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054455
Re: Re: Dynamic Redirector
I don't understand what you mean by the handling of the {rr} template. The approach I suggested, overriding getTargetRef, ignores the template argument entirely. --tim On Sat, Apr 27, 2013 at 2:54 PM, Grant gsing...@apache.org wrote: Hmm, digging in on this a bit more, I'm not sure it fully works for what I'm trying to do. The issue seems to be in the handling of the {rr} template. In other words, if I'm just redirecting a single URI to another (i.e. http://foo/a to http://bar/b), this approach works, but if I want to redirect all children URIs to the respective children URIs of the target. That is, if I have I request http://foo:port/a/b/c and I want to attach at http://foo:port/a and redirect to http://bar:port/b/c (by rewriting the target reference), it doesn't seem to work if I create a MyRedirector (my derivation of Redirector) that has an attach point of http://foo:port/a and a target template of {rr} whereas before in my static redirector I was doing http://bar:port/{rr} and everything was good. Thanks, Grant -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054455 -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054456
RE: Re: Re: Dynamic Redirector
I don't understand what you mean by the handling of the {rr} template. The approach I suggested, overriding getTargetRef, ignores the template argument entirely. In my old code, I had: URI = hardcoded URI to resource Redirector redir = new Redirector(router.getContext(), URI + {rr}, Redirector.MODE_SERVER_OUTBOUND); router.attach(, redir, Template.MODE_STARTS_WITH); So, when I pass in http://foo:port/a/b/c, it redirects to URI/a/b/c In my new code, I pass in the target template simply as {rr} and then iin the getTargetRef, I do: protected Reference getTargetRef(Request request, Response response) { URI serviceURI = serviceLocator.getServiceURI(service); //THIS looks up the location of the service // Create the template Template rt = new Template(this.targetTemplate); rt.setLogger(getLogger()); // Return the formatted target URI if (new Reference(this.targetTemplate).isRelative()) { // Be sure to keep the resource's base reference. //Reference baseRef = new Reference(serviceURI.uri); if (log.isInfoEnabled()) { log.info(dynRedir from {} to {}, request.getResourceRef(), serviceURI.uri); } String format = rt.format(request, response); try { return new Reference(new URI(serviceURI.uri.toString() + format)); } catch (URISyntaxException e) { log.error(Exception, e); throw new RuntimeException(e); } } return new Reference(rt.format(request, response)); } /// I attach my DynamicRedirector at, for example, /a. When I pass in http://foo:port/a/b/c;, I want it to select my DynamicRedirector due to the /a (I'm using STARTS_WITH mode) part and then redirect to the target by passing along b/c (i.e. the {rr} part) such that the new URL would be something like http://dynamicHost:port/b/c;, based on what my serviceLocator returns. Like I said, it works great if I'm just matching at /a, but it doesn't handle the /b/c part. AFAICT, the handle() methods in Restlet are continuing to resolve down to the last endpoint (i.e. b/c) even though it has a match at /a. I will see if I can work up a standalone test example to demonstrate it. -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054458
Re: Re: Re: Dynamic Redirector
I haven't dug into this code, but I suspect you aren't manipulating References properly. I advise printing out the intermediate steps of your Reference computation to see where it goes wrong. Also, the template argument to Redirector is ignored if you override getTargetRef. --tim On Sat, Apr 27, 2013 at 6:03 PM, Grant gsing...@apache.org wrote: I don't understand what you mean by the handling of the {rr} template. The approach I suggested, overriding getTargetRef, ignores the template argument entirely. In my old code, I had: URI = hardcoded URI to resource Redirector redir = new Redirector(router.getContext(), URI + {rr}, Redirector.MODE_SERVER_OUTBOUND); router.attach(, redir, Template.MODE_STARTS_WITH); So, when I pass in http://foo:port/a/b/c, it redirects to URI/a/b/c In my new code, I pass in the target template simply as {rr} and then iin the getTargetRef, I do: protected Reference getTargetRef(Request request, Response response) { URI serviceURI = serviceLocator.getServiceURI(service); //THIS looks up the location of the service // Create the template Template rt = new Template(this.targetTemplate); rt.setLogger(getLogger()); // Return the formatted target URI if (new Reference(this.targetTemplate).isRelative()) { // Be sure to keep the resource's base reference. //Reference baseRef = new Reference(serviceURI.uri); if (log.isInfoEnabled()) { log.info(dynRedir from {} to {}, request.getResourceRef(), serviceURI.uri); } String format = rt.format(request, response); try { return new Reference(new URI(serviceURI.uri.toString() + format)); } catch (URISyntaxException e) { log.error(Exception, e); throw new RuntimeException(e); } } return new Reference(rt.format(request, response)); } /// I attach my DynamicRedirector at, for example, /a. When I pass in http://foo:port/a/b/c;, I want it to select my DynamicRedirector due to the /a (I'm using STARTS_WITH mode) part and then redirect to the target by passing along b/c (i.e. the {rr} part) such that the new URL would be something like http://dynamicHost:port/b/c;, based on what my serviceLocator returns. Like I said, it works great if I'm just matching at /a, but it doesn't handle the /b/c part. AFAICT, the handle() methods in Restlet are continuing to resolve down to the last endpoint (i.e. b/c) even though it has a match at /a. I will see if I can work up a standalone test example to demonstrate it. -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054458 -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3054459
RE: Re: Dynamic Redirector
That works beautifully, thank you! For the record, I used what was in getTargetRef almost as is, except I replaced the baseRef with a dynamically discovered one (that I get from Zookeeper). Thanks, Grant -- http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447dsMessageId=3053466