cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Vadim Gritsenko <va...@reverycodes.com>
Subject Re: Proposed fix: crazy infinite loop w/ <ft:continuation-id>
Date Fri, 01 Apr 2005 19:32:50 GMT
Mark Lundquist wrote:
> 
> I tried passing the continuation ID as a hidden form parameter, using 
> <ft:continuation-id>. Until now, I've always put continuation IDs in the 
> URI, but in this application I really need to do it this way (and if I 
> can get this to work right, I'm going to do it this way again in the 
> future!).
> 
> The problem is that after the continuation is resumed, the response to 
> that request is generated by an internal redirect (via sendPage()) of 
> the request, which is of course matched against the sitemap, but since 
> the request still contains the "continuation-id" parameter, it hits on 
> that matcher and re-invokes the continuation, and it's "/déjà vu/ all 
> over again", forever and ever, amen.
> 
> So, (you smugly say :-), I should just move my continuation-id matcher 
> to the end of the pipeline, so that it only matches if nothing else did.
> 
> Well, the way I have designed the page flow in this app — which I think 
> is the Right Way, BTW — absolutely depends on always matching on a 
> continuation-id parameter in the "flow-originating request", and having 
> this in turn work in a "sane" manner. And there is absolutely no use 
> whatsoever for the continuation-id parameter, once the continuation has 
> been resumed. I don't think I should have to redesign my page flow to 
> something "worse", just to work around an onerous constraint on matching 
> the continuation-id! :-)
> 
> See below for an example scenario, representative of the sort of page 
> flow I'm implementing.
> But first, the proposed fix:
> 
> I've added this method to the oac.environment.Request interface:
> 
> public void killContinuation();
> 
> In an HttpRequest, this sets a flag which causes 
> getParameter("continuation-id") to return null. This is a workaround for 
> the lack of a removeParameter() method in HttpServletRequest (the 
> delegate).
> 
> Now, over to the flowscript side of CForms... in 
> Form.prototype.showForm(), after the call to sendPageAndWait(), I call 
> cocoon.request.killContinuation().
> 
> Works like a charm. No more infinitous loopage!
> 
> So, my questions:
> 
> • Is this a good fix? There isn't some better one that I am missing, is 
> there?

No, it's horrible.


> • My fix might seem like hacky special-case-ism. But it also seems like 
> adding a general removeParameter() method to these wrappers, while 
> certainly possible (it'd just be a HashSet), would be overkill to solve 
> a general problem that doesn't really exist (after all there is a reason 
> that HttpServletRequest has gotten along nicely all this time without 
> such a method). But maybe I'm wrong about that, and someone will tell my 
> why I really should add this as a removeParameter() method... WDYT?
> 
> I've prototyped this in the v2 version of Form, but I'll add it to "v1" 
> and v3 before submitting a patch.
> 
> -=-=-=--=
> 
> A simple example of why I need this: Suppose we are doing "lightweight 
> authentication" — i.e., using pure flowscript, w/o the AuthFW. This is 
> super-simple, but to break it way down in excruciating detail:
> 
> 1) The user requests a protected resource "/foo".
> 2) The sitemap dispatches to a flowscript controller function that 
> handles this request
> 3) Since this is a protected resource, the controller calls a flowscript 
> authorize() function
> 3) The user isn't logged in, so authorize() invokes a login form (a 
> CForms form). (*N.B.:* the browser is /not/ redirected to "the login 
> page". The address bar shows "/foo").
> 3) The users fills out and submits the form, which is a <form action=""> 
> so it requests "/foo" again, this time with some (additional?) POST 
> parameters: userName, password, and continuation-id.
> 4) The continuation matcher in the sitemap hits, and the continuation is 
> resumed.
> 5) The login was successful, so the authorize() function returns 
> (otherwise, it just loops and reissues the login form, i.e. return == 
> success).

Note: flow function can not return. It can do sendPage,redirect - but it can't 
simply return.


> 6) The caller of of authorize() proceeds and generates the reply to the 
> request for "/foo".
> 7) The browser receives the reply and renders the page. The address bar 
> shows "/foo", the resource that was originally requested.

I see several possible ways of solving your issue without crazy hacks.

  * Move view rendering into the internal-only pipeline. That's how it
    (usually) should be with the flow.

  * If you don't like above, issue a redirect in the step (5) - you'll
    loose continuation ID parameter in the process.

  * Third option. The best approach to implement your login scenario
    is to write custom auth action. If user is authenticated, you
    return a map, sitemap shows the view (nested in the map:act).
    If he is not, you return null and sitemap shows the login form
    (you can use flow and forms there as it is now):

    <map:act type="myauth">
      <map:match pattern="*">
        <!-- generate page here -->
      </map:match>
    </map:act>
    <map:call function="login"
              continuation-id="{request-param:continuation}"/>


Vadim

Mime
View raw message