Grisha wrote ..
> 
> If I understand this correctly, then +1.
> 
> ...though I'm wondering if anyone will actually try to do something as
> arcane as dynamicaly registering non-content handers? :-)

I agree, it might not be a totally realistic scenario, but then now that
I have checked in a change to make req.handler writable, the system
is becoming flexible enough that it may actually be reasonable to do
it for some reason.

Specifically, with the change to make req.handler writable, instead of
using SetHandler/AddHandler to have mod_mime internally set
req.handler to "mod_python", you could define your own type handler
which did it.

  def typehandler(req): 
    if os.path.splitext(req.filename)[1] == ".py": 
      req.handler = "mod_python" 
      req.add_handler("PythonHandler","mod_python.publisher") 
      return apache.OK 
    return apache.DECLINED 

You might even at the same time want to register a fixup handler
to do stuff prior to the response phase being run:

  def typehandler(req): 
    if os.path.splitext(req.filename)[1] == ".py": 
      req.handler = "mod_python" 
      req.add_handler("PythonFixupHandler","manage_session_object")
      req.add_handler("PythonHandler","mod_python.publisher") 
      return apache.OK 
    return apache.DECLINED 

For example, you might introduce a fixup handler which ensures that
a session object is created and put in req.session. This is a lot cleaner
than what most people do, which is to put a call to the session manager
code in every single published function.

Graham

> On Tue, 21 Feb 2006, Jim Gallacher wrote:
> 
> > Nice summary.
> > +1 for the change.
> >
> > Jim
> >
> > Graham Dumpleton wrote:
> >> Jim Gallacher wrote ..
> >> 
> >>> I don't have alot more to say on these last 2 emails. I think you are
> on
> >>> the right path here.
> >> 
> >> 
> >> Okay, I think I have a good plan now.
> >> 
> >> To summarise the whole issue, the way Apache treats multiple handlers
> in
> >> a single phase for non content handler phases is as follows:
> >> 
> >>   PostReadRequestHandler   RUN_ALL
> >>   TransHandler             RUN_FIRST
> >>   MapToStorageHandler      RUN_FIRST
> >>   InitHandler              RUN_ALL
> >>   HeaderParserHandler      RUN_ALL
> >>   AccessHandler            RUN_ALL
> >>   AuthenHandler            RUN_FIRST
> >>   AuthzHandler             RUN_FIRST
> >>   TypeHandler              RUN_FIRST
> >>   FixupHandler             RUN_ALL
> >> 
> >>   LogHandler               RUN_ALL
> >> 
> >> RUN_ALL means run all handlers until one returns something other than
> OK
> >> or DECLINED. Thus, handler needs to return DONE or an error to have
> it 
> >> stop
> >> processing for that phase.
> >> 
> >> RUN_FIRST means run all handlers while they return DECLINED. Thus, needs
> >> handler to return OK, DONE or error to have it stop processing for that
> >> phase.
> >> 
> >> Where multiple handlers are registered within mod_python for a single
> >> phase it doesn't behave like either of these. In mod_python it will
> keep
> >> running the handlers only while OK is returned. Returning DECLINED
> >> causes it to stop. This existing behaviour can be described (like 
> >> mod_perl)
> >> as stacked handlers.
> >> 
> >> Having non content handler phases behave differently to how Apache does
> >> it causes problems. For example things like a string of authentication
> >> handlers which only say OK when they handle the authentication type,
> >> can't be implemented properly. In Apache, it should stop the first time
> >> one returns OK, but in mod_python it will keep running the handlers
> >> in that phase.
> >> 
> >> In summary, it needs to behave more like Apache for the non content
> >> handler phases.
> >> 
> >> In respect of the content handler phase itself, in practice only one
> >> handler
> >> module is supposed to implement it. At the Apache level there is no
> >> concept of different Apache modules having goes at the content handler
> >> phase and returning DECLINED if they don't want to handle it. This is
> >> reflected in how in the type handler phase, selection of the module
> to
> >> deliver content is usually done by setting the single valued req.handler
> >> string. Although, when using mod_python this is done implicitly by
> >> setting the SetHandler/AddHandler directives and mod_negotiation then
> >> in turn setting req.handler to be mod_python for you.
> >> 
> >> Because mod_python when executed for the content handler phase is
> >> the only thing generating the content, the existing mechanism of
> >> stacked handlers and how the status is handled is fine within just
> >> the content handler phase. Can thus keep that as is and no chance of
> >> stuffing up existing systems.
> >> 
> >> Where another phase calls req.add_handler() to add a handler or multiple
> >> handlers for the "PythonHandler" (content) phase, these will be added
> in
> >> a stacked manner within that phase. This also is the same as it works
> now.
> >> There would be non need to have a new function to add stacked handlers
> >> as that behaviour would be dictated by phase being "PythonHandler".
> >> 
> >> For all the non content handler phases though, the current stacked
> >> handlers algorithm used by mod_python would be replaced with how
> >> Apache does it. That is, within multiple handlers registered with 
> >> mod_python
> >> for non content handler phase, it would use RUN_FIRST or RUN_ALL
> >> algorithm as appropriate for the phase.
> >> 
> >> For those which use RUN_ALL, this wouldn't be much different than what
> >> mod_python does now except that returning DECLINED would cause it
> >> to go to next mod_python handler in that phase instead of stopping.
> >> It is highly unlikely that this change would have an impact as returning
> >> DECLINED in RUN_ALL phases for how mod_python currently implements
> >> it, tends not to be useful and can't see that anyone would have been
> using 
> >> it.
> >> 
> >> For those which use RUN_FIRST, the difference would be significant as
> >> reurning OK will now cause it to stop instead of going to next mod_python
> >> handler in the phase. Personally I don't think this would be a drama
> as
> >> not many people would be using these phases and highly unlikely that
> >> someone would have listed multiple handlers for such phases. If they
> had
> >> and knew what they were doing, they should have long ago realised that
> >> the current behaviour was a bit broken and it even probably stopped
> them
> >> from doing what they wanted unless they fudged it.
> >> 
> >> As to use of req.add_handler() for non content handler phases, each
> call
> >> would create a distinct handler, ie., no stacking of handlers at all.
> No
> >> separate function is required though, as slight change in behaviour
> >> determine form phase specified.
> >> 
> >> To sum up, I think these changes would have minimal if no impact as
> >> where changes are significant, it isn't likely to overlap with existing
> >> code
> >> as shortcomings in current system would have mean't people wouldn't
> >> have been doing the sorts of things that may have been impacted.
> >> 
> >> Therefore, I don't see a need for this to be switch enabled and the
> >> change could just be made and merely documented.
> >> 
> >> Luckily the changes to make it work like above should be fairly easy.
> All
> >> it will entail is changing CallBack.HandlerDispatch() to treat status
> >> differently dependent on phase. No changes to req.add_handler() or
> >> code processing directives will be required.
> >> 
> >> Graham
> >> 
> >> 
> >

Reply via email to