cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Eric E. Meyer" <eric.meyer.coc...@quoininc.com>
Subject Re: Proposed fix: crazy infinite loop w/ <ft:continuation-id>
Date Fri, 01 Apr 2005 19:42:00 GMT
This is how I work with hidden continuation ids since my form posts.

You can select based upon the request:method - continuing only on POST:

            <map:select type="oacl-simple">
                <map:parameter name="value" value="{request:method}"/>
                <map:when test="GET">
                    <map:call function="functionName">
                        <map:parameter name="searchType"
                            value="{0}" />
                    </map:call>
                </map:when>
                <map:when test="POST">
                    <map:call
                        continuation="{request-param:continuation-id}"
                    />
                </map:when>
            </map:select>

Regards,
Eric

Vadim Gritsenko wrote:

> 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