sethandlers question - modperl

This is a discussion on sethandlers question - modperl ; Hi. Still around a new perl AAA module I'm writing, a question : If I have a Location like so : SetHandler jakarta-servlet SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg| js |html?)$" no-jk PerlXXXHandler My::Module->some_method ... ("jakarta-servlet" above means mod_jk --> Tomcat) (and PerlXXXHandler ...

+ Reply to Thread
Results 1 to 13 of 13

Thread: sethandlers question

  1. sethandlers question

    Hi.

    Still around a new perl AAA module I'm writing, a question :

    If I have a Location like so :



    SetHandler jakarta-servlet
    SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk

    PerlXXXHandler My::Module->some_method

    ...



    ("jakarta-servlet" above means mod_jk --> Tomcat)
    (and PerlXXXHandler being any kind of Perl HTTP Handler running soon enough)

    The Question :
    Is it possible, in the PerlXXXHandler, on a request-by-request base, to
    "disable" the jakarta-servlet handler, and install the following instead

    SetHandler modperl
    PerlResponseHandler My::Module->some_other_method

    ?

    I know that I can do something like the above for regular static pages,
    and I use this already :
    $r->handler('modperl');
    $r->set_handlers(PerlAuthzHandler => []); # stop authorization from
    running
    $r->set_handlers(PerlResponseHandler => \&_send_login_form);


    However, when I try to do the same in a Location like the above, it
    seems that the jakarta-servlet handler runs anyway, and my
    PerlResponseHandler is never called.

    The reason I want to do it that way, is that it allows me, in the
    substituted PerlResponseHandler, to do some stuff to the login page that
    I send, which would be more complicated to do via a simple redirect.
    Or ?

    (One thing I have not tried (nor researched) e.g., is to see if I can
    install both modperl and the jakarta-servlet as handlers, and disable
    the modperl handler if the condition is /not/ met.)

    Thanks


  2. Re: sethandlers question

    On Sun 12 Oct 2008, André Warnier wrote:
    >
    >
    > * *SetHandler jakarta-servlet
    > * *SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
    >
    > * *PerlXXXHandler My::Module->some_method
    >
    > * *...
    >
    >

    >
    > ("jakarta-servlet" above means mod_jk --> Tomcat)
    > (and PerlXXXHandler being any kind of Perl HTTP Handler running soon
    > enough)
    >
    > The Question :
    > Is it possible, in the PerlXXXHandler, on a request-by-request base,
    > to "disable" the jakarta-servlet handler, and install the following
    > instead
    >
    > * *SetHandler modperl
    > * *PerlResponseHandler My::Module->some_other_method
    >
    > ?
    >
    > I know that I can do something like the above for regular static
    > pages, and I use this already :
    > * *$r->handler('modperl');
    > * *$r->set_handlers(PerlAuthzHandler => []); # stop authorization
    > from running
    > * *$r->set_handlers(PerlResponseHandler => \&_send_login_form);
    >
    >
    > However, when I try to do the same in a Location like the above, it
    > seems that the jakarta-servlet handler runs anyway, and my
    > PerlResponseHandler is never called.


    Does that piece of code run in a /Perl(PostReadRequest|Trans|
    MapToStorage)Handler/ ?

    Please, have a look again at the ap_process_request_internal() function
    in httpd-2.x.y/server/request.c. This function implements almost the
    complete request cycle (save PostReadRequest, Response and Log).

    Just after ap_run_translate_name(), that is the PerlTransHandler, you'll
    see this piece:

    /* Reset to the server default config prior to running
    map_to_storage
    */
    r->per_dir_config = r->server->lookup_defaults;

    if ((access_status = ap_run_map_to_storage(r))) {
    /* This request wasn't in storage (e.g. TRACE) */
    return access_status;
    }

    /* Rerun the location walk, which overrides any map_to_storage
    config.
    */
    if ((access_status = ap_location_walk(r))) {
    return access_status;
    }

    /* Only on the main request! */
    if (r->main == NULL) {
    if ((access_status = ap_run_header_parser(r))) {
    return access_status;
    }
    }
    ...

    The line "r->per_dir_config = r->server->lookup_defaults;" resets all
    request specific configurations applied so far. After that line the
    request is configured as if no Directory/Location or other container
    were present in your httpd.conf. Next comes MapToStorage. Here
    Directory, DirectoryMatch, Files and FilesMatch containers are applied
    to the request. Then, and this is what I think hits you, comes an
    ap_location_walk. Here Location containers are applied. So, your
    SetHandler inside the Location overrides any $r->handler seen before.

    After the ap_location_walk comes the PerlHeaderParserHandler. But it is
    skipped for subrequests. A further examination will show you that the
    next phase that is run by all requests is the PerlTypeHandler just
    before Fixup. So, move your "$r->handler('modperl');" to one of those
    and it will work. I prefer Fixup but that is based only on the fact
    that it is documented as do-what-you-want phase. There are directives
    that change the handler in the type-checker phase. In fact the
    AddHandler directive works that way. Mod_mime looks at the file
    extension and adjusts the handler, e.g "AddHandler cgi-script .pl". So
    using Fixup your module is the last to kick in.

    To carry state around use pnotes, notes or subprocess_env.

    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


  3. Re: sethandlers question

    Hi Torsten.
    Once again, I thank you for the time spent researching and answering my
    question(s).
    Unfortunately, I am less fluent in C than you (which is why after all I
    like and use mod_perl), so sometimes referring me to the C code is not
    as enlightening to me as it undoubtedly is to you. But I am trying to
    follow, nevertheless.

    Torsten Foertsch wrote:
    > On Sun 12 Oct 2008, André Warnier wrote:
    >>
    >>
    >> SetHandler jakarta-servlet
    >> SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
    >>
    >> PerlXXXHandler My::Module->some_method
    >>
    >> ...
    >>
    >>

    >>
    >> ("jakarta-servlet" above means mod_jk --> Tomcat)
    >> (and PerlXXXHandler being any kind of Perl HTTP Handler running soon
    >> enough)
    >>
    >> The Question :
    >> Is it possible, in the PerlXXXHandler, on a request-by-request base,
    >> to "disable" the jakarta-servlet handler, and install the following
    >> instead
    >>
    >> SetHandler modperl
    >> PerlResponseHandler My::Module->some_other_method
    >>
    >> ?
    >>
    >> I know that I can do something like the above for regular static
    >> pages, and I use this already :
    >> $r->handler('modperl');
    >> $r->set_handlers(PerlAuthzHandler => []); # stop authorization
    >> from running
    >> $r->set_handlers(PerlResponseHandler => \&_send_login_form);
    >>
    >>
    >> However, when I try to do the same in a Location like the above, it
    >> seems that the jakarta-servlet handler runs anyway, and my
    >> PerlResponseHandler is never called.

    >
    > Does that piece of code run in a /Perl(PostReadRequest|Trans|
    > MapToStorage)Handler/ ?


    No, at the moment it runs in a PerlAuthenHandler.
    As explained the other thread (requests and subrequests), I thought it
    was more elegant and mod_perl-ish, instead of doing a re-direct to a
    login page if the user needed authentifying, to having the login page
    returned by a content handler.
    (One main reason is that it allows me, in that content handler,to
    "filter" the login page and insert in it, things I have stored
    previously in $r->pnotes().)
    For that thus, when the user is not authenticated when the request hits
    the PerlAuthenHandler, this handler tries to set the content handler
    (PerlResponseHandler) to the method send_login_form() in the same module.
    This works fine when the previous content handler is Apache's default,
    iow for static pages. But it fails miserably when there is already a
    specific content handler (like mod_jk) for this Location.

    >
    > Please, have a look again at the ap_process_request_internal() function
    > in httpd-2.x.y/server/request.c.

    I would first have to know where this thing is. I have never so far
    looked at the Apache source code, so I need some pointers there.
    Not that if I look, I would necessarily understand much of it, but I can
    try.
    Now, why would I, since you provide the nice explanation below ?

    This function implements almost the
    > complete request cycle (save PostReadRequest, Response and Log).
    >
    > Just after ap_run_translate_name(), that is the PerlTransHandler, you'll
    > see this piece:
    >
    > /* Reset to the server default config prior to running
    > map_to_storage
    > */
    > r->per_dir_config = r->server->lookup_defaults;
    >
    > if ((access_status = ap_run_map_to_storage(r))) {
    > /* This request wasn't in storage (e.g. TRACE) */
    > return access_status;
    > }
    >
    > /* Rerun the location walk, which overrides any map_to_storage
    > config.
    > */
    > if ((access_status = ap_location_walk(r))) {
    > return access_status;
    > }
    >
    > /* Only on the main request! */
    > if (r->main == NULL) {
    > if ((access_status = ap_run_header_parser(r))) {
    > return access_status;
    > }
    > }
    > ...
    >
    > The line "r->per_dir_config = r->server->lookup_defaults;" resets all
    > request specific configurations applied so far. After that line the
    > request is configured as if no Directory/Location or other container
    > were present in your httpd.conf. Next comes MapToStorage. Here
    > Directory, DirectoryMatch, Files and FilesMatch containers are applied
    > to the request.

    So, you mean that for every and each request, Apache re-configures
    itself ? If that is so, it is quite amazing the speed at which it can
    serve a page..

    Then, and this is what I think hits you, comes an
    > ap_location_walk. Here Location containers are applied. So, your
    > SetHandler inside the Location overrides any $r->handler seen before.

    Well, I am not sure :
    The handler set in the configuration file for that Location, is
    originally "jakarta-servlet" (as per the snippet below).
    It is I, in my PerlAuthenHandler, who is trying to reset this to
    "modperl", and in mod_perl, to my send_login_page() method.
    Before I do that, there is no $r->handler nor PerlResponseHandler set.

    I may be misunderstanding what you say above of course..

    >
    > After the ap_location_walk comes the PerlHeaderParserHandler. But it is
    > skipped for subrequests.

    That's fine, we are always in a main request here.

    A further examination will show you
    (probably not)
    that the
    > next phase that is run by all requests is the PerlTypeHandler just
    > before Fixup. So, move your "$r->handler('modperl');" to one of those
    > and it will work.

    I don't think I can do that, unless I want the PerlTypeHandler or
    PerlFixupHandler to become an authentication handler. That would
    probably for one upset Adam, for two be kind of funky, no ?

    I prefer Fixup but that is based only on the fact
    > that it is documented as do-what-you-want phase. There are directives
    > that change the handler in the type-checker phase. In fact the
    > AddHandler directive works that way. Mod_mime looks at the file
    > extension and adjusts the handler, e.g "AddHandler cgi-script .pl". So
    > using Fixup your module is the last to kick in.


    Now, in summary :
    This is a very specialised authentication module, meant to be used in
    very specific circumstances and not for general usage. I control the
    environment, so I can pretty much do what I want as long as it does not
    crash the system or present some big security hole or the like.

    In my case, that containing the
    sethandler jakarta-servlet
    is pretty much unique: it is not a sub- or super-location of anything
    else, and it fulfills only one very narrow purpose.
    To my knowledge, there will be no other module playing a role there,
    other than the jakarta-servlet initial handler, plus whatever I decide
    to put in there as mod_perl modules and methods.
    This for the entire duration of one request.

    Now, assuming I have no other stuff in there than the following lines

    SetHandler jakarta-servlet
    SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk

    AuthType MyModule
    AuthName MyXyzApp
    PerlSetVar MyModule_var1 "value"
    PerlAccessHandler My::Module->some_access_method
    PerlAuthenHandler My::Module->some_auth_method
    PerlAuthzHandler My::Module->some_authz_method
    require valid-user



    then, if I understand correctly what you write above, since I have no
    PerlTransHandler, nor Fixup, etc.. I should be able to do the same in
    the PerlAuthenHandler, is it no so ?
    Or am I still confused about the order in which things happen ?

    Or, a thought that just occurred to me, is the solution for me (stopping
    jakarta-servlet from running and running my PerlresponseHandler
    instead), as easy as setting the "no-jk" variable (if I can do that
    within my PerlAuthenHandler, and how) ?

    Or, another thought that just occurred : can I comment out the
    "SetHandler jakarta-servlet" originally, set my PerlresponseHandler as
    the default handler in the , and then *if the user is
    authenticated* (the contrary of my current condition), *set* the content
    handler to be jakarta-servlet instead of modperl ?

    >
    > To carry state around use pnotes

    (that's what I use mostly)
    , notes or subprocess_env.
    >



  4. Re: sethandlers question

    On Mon 13 Oct 2008, André Warnier wrote:
    > As explained the other thread (requests and subrequests), I thought
    > it was more elegant and mod_perl-ish, instead of doing a re-direct to
    > a login page if the user needed authentifying, to having the login
    > page returned by a content handler.


    The apache-way to do this has a name: ErrorDocument or in mod_perl
    $r->custom_response. Configure an ErrorDocument for 403 and return
    HTTP_FORBIDDEN in your A...Handler. That has the benefit that the 403
    status is logged and that the browser (think about search engines) sees
    it. But the custom response page must be larger than 512 bytes or
    you'll encounter problems with IE. If you don't care about that you can
    use $r->internal_redirect. That is a bit less work to do for your
    server.

    > > Please, have a look again at the ap_process_request_internal()
    > > function in httpd-2.x.y/server/request.c.

    >
    > I would first have to know where this thing is. *I have never so far
    > looked at the Apache source code, so I need some pointers there.
    > Not that if I look, I would necessarily understand much of it, but I
    > can try.
    > Now, why would I, since you provide the nice explanation below ?


    Out of curiosity! Just download the apache source untar it and open in
    in your favorite editor. C is not that much different from perl and the
    request.c file is really easy to read. You don't have to modify it,
    just try to understand what is going on!

    > So, you mean that for every and each request, Apache re-configures
    > itself ? *If that is so, it is quite amazing the speed at which it
    > can serve a page..


    Just keep in mind for the following that apache is originally designed
    to have a static configuration. So at start it splits the configuration
    into blocks, one holds the basic config that is outside all containers
    and others for each Location/Directory/etc. From those blocks it
    generates pre-parsed configuration vectors. At runtime each request
    starts with the basic config fetched from r->server->lookup_defaults
    then it looks for other vectors matching the request and merges them.

    But there is another configuration source, .htaccess. Those are read in,
    compiled and merged in the same function (ap_directory_walk() (hard to
    understand)) that applies Directory containers (called from
    ap_run_map_to_storage()).

    With mod_perl comes yet another configuration source, $r->add_config.
    This is implemented very similar to .htaccess only the directives are
    not read from a file but from memory and they are compiled and merged
    at the time $r->add_config is called.

    > Well, I am not sure :
    > The handler set in the configuration file for that Location, is
    > originally "jakarta-servlet" (as per the snippet below).
    > It is I, in my PerlAuthenHandler, who is trying to reset this to
    > "modperl", and in mod_perl, to my send_login_page() method.
    > Before I do that, there is no $r->handler nor PerlResponseHandler
    > set.


    So, why not issue a $r->internal_redirect. I don't exactly know when the
    SetHandler directive sets $r->handler. Maybe it is done in the type
    checker phase. So perhaps you have to move your code to Fixup or use
    $r->add_config(['SetHandler modperl']).

    > I don't think I can do that, unless I want the PerlTypeHandler or
    > PerlFixupHandler to become an authentication handler. *That would
    > probably for one upset Adam, for two be kind of funky, no ?


    Why not?

    if( $override_handler ) {
    $r->push_handlers( PerlFixupHandler=>__PACKAGE__.'::fixup' );
    $r->pnotes->{override_handler}='modperl';
    }
    ...
    sub fixup {
    $_[0]->handler($_[0]->pnotes->{override_handler};
    return Apache2::Const::OK;
    }

    > Now, in summary :
    > This is a very specialised authentication module, meant to be used in
    > very specific circumstances and not for general usage. *I control the
    > environment, so I can pretty much do what I want as long as it does
    > not crash the system or present some big security hole or the like.
    >
    > In my case, that containing the
    > sethandler jakarta-servlet
    > is pretty much unique: it is not a sub- or super-location of anything
    > else, and it fulfills only one very narrow purpose.
    > To my knowledge, there will be no other module playing a role there,
    > other than the jakarta-servlet initial handler, plus whatever I
    > decide to put in there as mod_perl modules and methods.
    > This for the entire duration of one request.
    >
    > Now, assuming I have no other stuff in there than the following lines
    >
    > * * SetHandler jakarta-servlet
    > * * SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
    >
    > * * AuthType MyModule
    > * * AuthName MyXyzApp
    > * * PerlSetVar MyModule_var1 "value"
    > * * PerlAccessHandler My::Module->some_access_method
    > * * PerlAuthenHandler My::Module->some_auth_method
    > * * PerlAuthzHandler My::Module->some_authz_method
    > * * require valid-user
    >
    >

    >
    > then, if I understand correctly what you write above, since I have no
    > PerlTransHandler, nor Fixup, etc.. *I should be able to do the same
    > in the PerlAuthenHandler, is it no so ?
    > Or am I still confused about the order in which things happen ?


    I think I am confused a bit here.

    > Or, a thought that just occurred to me, is the solution for me
    > (stopping jakarta-servlet from running and running my
    > PerlresponseHandler instead), as easy as setting the "no-jk" variable
    > (if I can do that within my PerlAuthenHandler, and how) ?


    I was tempted to suggest that. But I don't know nothing about jakarta.
    If you want to try use $r->subprocess_env->{'no-jk'}=1;

    > Or, another thought that just occurred : can I comment out the
    > "SetHandler jakarta-servlet" originally, set my PerlresponseHandler
    > as the default handler in the , and then *if the user is
    > authenticated* (the contrary of my current condition), *set* the
    > content handler to be jakarta-servlet instead of modperl ?


    Of course.

    I think the best solution is the ErrorDocument or custom_response. The
    second best is the internal_redirect. Both need a way to address you
    login form by an URI.


    SetHandler modperl
    PerlResponseHandler My::LoginForm


    package My::LoginForm;
    sub handler {
    my ($r)=@_;
    my $original_req=$r->prev;
    unless( $original_req ) {
    $r->log_reason("/login is to be called as internal redirect");
    return Apache2::Const::SERVER_ERROR;
    }
    my $original_pnotes=$original_req->pnotes;
    ...
    return Apache2::Const::OK;
    }

    ErrorDocument 403 /login


    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


  5. Re: sethandlers question

    Hi.

    I have read and pondered your earlier responses, and I am sure that the
    correct solution is somewhere around the ErrorDocument or the
    $r->internal_redirect.
    But I wanted to exhaust the other possibilities first, for the sake of
    completeness and also to learn more about this all.

    So one little bit at a time :

    reminder of my config :
    >>
    >> SetHandler jakarta-servlet
    >> SetEnvIf REQUEST_URI "\.(htm|web|css|gif|jpg|js|html?)$" no-jk
    >>
    >> AuthType MyModule
    >> AuthName MyXyzApp
    >> PerlSetVar MyModule_var1 "value"
    >> PerlAccessHandler My::Module->some_access_method
    >> PerlAuthenHandler My::Module->some_auth_method
    >> PerlAuthzHandler My::Module->some_authz_method
    >> require valid-user
    >>
    >>
    >>

    And, in summary, what I was trying to do is :
    if the PerlAuthenHandler finds that the request is not authenticated,
    then it tries to change the response handler for this request, from the
    original "jakarta-servlet" handler, to my own response handler, which in
    fact returns a login page.
    (I need something "active" to return the login page, because I need to
    insert some data into the login page prior to returning it).

    And for that I used this code in the PerlAuthenHandler :

    # set our own response handler
    $r->handler('modperl');
    $r->set_handlers(PerlResponseHandler => \&_send_login_form);
    return OK;


    One of the possibilities envisioned previously was :
    >
    >> Or, a thought that just occurred to me, is the solution for me
    >> (stopping jakarta-servlet from running and running my
    >> PerlresponseHandler instead), as easy as setting the "no-jk" variable
    >> (if I can do that within my PerlAuthenHandler, and how) ?

    >
    > I was tempted to suggest that. But I don't know nothing about jakarta.
    > If you want to try use $r->subprocess_env->{'no-jk'}=1;
    >


    I tried this, because it was the smallest possible change to my module.
    It works, in the sense that it sets the "no-jk" variable, which
    consequently has the effect of making the "jakarta-servlet" handler
    above not process this link.
    But it is not a solution for me, since what happens is that the
    jakarta-servlet handler is in fact still executed by Apache as the
    response handler, but it probably just returns DECLINED.
    Then Apache seems to handle the response with its own default handler,
    which results in a "404 not found" error.

    The other possibility looked at was :
    > Or, another thought that just occurred : can I comment out the
    > > "SetHandler jakarta-servlet" originally, set my PerlresponseHandler
    > > as the default handler in the , and then *if the user is
    > > authenticated* (the contrary of my current condition), *set* the
    > > content handler to be jakarta-servlet instead of modperl ?


    > Torsten said : Of course.

    But Torsten did not say how, and I don't know how to do that.
    How can I set the Apache response handler to be "xyz" ? All I have at
    this point is the name of that handler : "jakarta-servlet".
    This is not a perl handler, it is mod_jk.so, the Apache/Tomcat AJP
    connector. (And I do not need code, I just need a pointer in the right
    direction).

    This is now purely for curiosity and for future reference, because after
    your previous explanations, I am convinced that this is not the right
    solution for the current problem.

    In the meantime, I'll go have a look at $r->internal_redirect, which is
    probably the correct solution.


  6. Re: sethandlers question

    On Tue 14 Oct 2008, André Warnier wrote:
    > reminder of my config :
    > >>
    > >> * * SetHandler jakarta-servlet

    ...
    > >>

    >
    > And, in summary, what I was trying to do is :
    > if the PerlAuthenHandler finds that the request is not authenticated,
    > then it tries to change the response handler for this request, from
    > the original "jakarta-servlet" handler, to my own response handler,
    > which in fact returns a login page.
    > (I need something "active" to return the login page, because I need
    > to insert some data into the login page prior to returning it).
    >
    > And for that I used this code in the PerlAuthenHandler :
    >
    > # set our own response handler
    > $r->handler('modperl');
    > $r->set_handlers(PerlResponseHandler => \&_send_login_form);
    > return OK;


    The problem is the $r->handler statement. The program flow is this:

    - ...
    - uri translation
    - map to storage
    - Location container is applied
    the SetHandler directive is applied to the requests configuration
    structure. That does not mean $r->handler is set. It is simply noted
    there is a SetHandler directive active for the request.
    - aaa
    - ...
    - fixup
    the SetHandler value is copied to $r->handler. See
    httpd-2.x.y/server/core.c:core_override_type()

    if (conf->handler && strcmp(conf->handler, "none"))
    r->handler = conf->handler;

    That means $r->handler is set only if there was a SetHandler directive
    and if it was not "SetHandler none".

    So, that leads us to 4 possible solutions:

    1) remove the SetHandler directive from the Location container and set
    $r->handler either to jakarta-servelet or to modperl in your aaa
    handler. It won't be touched if other modules don't kick in. mod_dir
    comes to mind but it reads (fixup handler):

    /* In case mod_mime wasn't present, and no handler was assigned. */
    if (!r->handler) {
    r->handler = DIR_MAGIC_TYPE;
    }

    So, that's not a problem. But there may be other modules that don't
    check that.

    2) replace $r->handler('modperl') in the aaa phase by
    $r->add_config(['SetHandler modperl']). This way you override the
    handler set in the configuration structure. In the fixup phase it is
    then automagically copied to $r->handler.

    3) leave the $r->handler('modperl') and add a
    $r->add_config(['SetHandler none']);

    4) set $r->handler in a fixup handler.

    $r->add_config works very similar to


    your directives


    The only difference is the time when it is applied to the config struct.
    That config is reset after the translation phase. So it is useless to
    try $r->add_config before. Location containers from the httpd.conf are
    applied after MapToStorage. So anything you do in your own MapToStorage
    handler can be overridden in Location containers even if your handler
    returns OK to skip the core MapToStorage handler.

    But anything applied after that, that means from the header-parser phase
    onward overrides the httpd.conf settings.

    > One of the possibilities envisioned previously was :
    > >> Or, a thought that just occurred to me, is the solution for me
    > >> (stopping jakarta-servlet from running and running my
    > >> PerlresponseHandler instead), as easy as setting the "no-jk"
    > >> variable (if I can do that within my PerlAuthenHandler, and how) ?

    > >
    > > I was tempted to suggest that. But I don't know nothing about
    > > jakarta. If you want to try use $r->subprocess_env->{'no-jk'}=1;

    >
    > I tried this, because it was the smallest possible change to my
    > module. It works, in the sense that it sets the "no-jk" variable,
    > which consequently has the effect of making the "jakarta-servlet"
    > handler above not process this link.
    > But it is not a solution for me, since what happens is that the
    > jakarta-servlet handler is in fact still executed by Apache as the
    > response handler, but it probably just returns DECLINED.


    That's what I thought it would.

    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


  7. Re: sethandlers question

    I am trying the 4 receipes one after the other, in order of easiest to
    more complicated.

    Torsten Foertsch wrote:
    >
    > 2) replace $r->handler('modperl') in the aaa phase by
    > $r->add_config(['SetHandler modperl']). This way you override the
    > handler set in the configuration structure. In the fixup phase it is
    > then automagically copied to $r->handler.

    When I try this, I get an Apache error with the following logfile message :
    [Tue Oct 14 16:19:39 2008] [error] [client 84.158.163.207]
    $r->add_config() has failed: SetHandler not allowed here at
    /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 416.\n

    >
    > 3) leave the $r->handler('modperl') and add a
    > $r->add_config(['SetHandler none']);
    >

    When I try this, I get an Apache error with the following logfile message :
    [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207]
    $r->add_config() has failed: SetHandler not allowed here at
    /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n


    So it seems that something does not like the $r->add_config from within
    an AAA method, or at least not when trying to change the handler.

    I'll try the others now.


  8. Re: sethandlers question

    On Tue 14 Oct 2008, André Warnier wrote:
    > When I try this, I get an Apache error with the following logfile
    > message : [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207]
    > $r->add_config() has failed: SetHandler not allowed here at
    > /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n


    That is an apache error. SetHandler needs the FileInfo override flag,
    see http://httpd.apache.org/docs/2.2/mod...tml#sethandler. So, the
    correct command would be:

    $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO)

    or simpler

    $r->add_config(['SetHandler ...'], ~0)

    (since you know what directive you are adding).

    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


  9. Re: sethandlers question

    André Warnier wrote:
    > I am trying the 4 receipes one after the other, in order of easiest to
    > more complicated.
    >
    > Torsten Foertsch wrote:
    >>
    >> 2) replace $r->handler('modperl') in the aaa phase by
    >> $r->add_config(['SetHandler modperl']). This way you override the
    >> handler set in the configuration structure. In the fixup phase it is
    >> then automagically copied to $r->handler.

    > When I try this, I get an Apache error with the following logfile message :
    > [Tue Oct 14 16:19:39 2008] [error] [client 84.158.163.207]
    > $r->add_config() has failed: SetHandler not allowed here at
    > /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 416.\n
    >
    >>
    >> 3) leave the $r->handler('modperl') and add a
    >> $r->add_config(['SetHandler none']);
    >>

    > When I try this, I get an Apache error with the following logfile message :
    > [Tue Oct 14 16:10:40 2008] [error] [client 84.158.163.207]
    > $r->add_config() has failed: SetHandler not allowed here at
    > /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line 414.\n
    >
    >
    > So it seems that something does not like the $r->add_config from within
    > an AAA method, or at least not when trying to change the handler.
    >


    But
    > 4) set $r->handler in a fixup handler.


    this works :

    $r->set_handlers(PerlAuthzHandler => []); # disable authorization
    $r->set_handlers(PerlResponseHandler => \&_send_login_form);
    $r->set_handlers(PerlFixupHandler => \{$_[0]->handler('modperl')});


    Many, many thanks for all the explanations and tips.

    I doubly appreciate not only because my immediate problem is solved, but
    also because I learned a lot in the process.

    It seems to me that this whole thread could be collected and re-arranged
    into a Tutorial on mod_perl phases, authentication, interactions with
    Apache etc.. but honestly at the moment I don't know where to begin.


  10. Re: sethandlers question

    On Tue 14 Oct 2008, André Warnier wrote:
    > I doubly appreciate not only because my immediate problem is solved,
    > but also because I learned a lot in the process.


    Try the $r->add_config again with the right override flag (OR_FILEINFO)
    and you'll see it will also work.

    > It seems to me that this whole thread could be collected and
    > re-arranged into a Tutorial on mod_perl phases, authentication,
    > interactions with Apache etc.. *but honestly at the moment I don't
    > know where to begin.


    Find a place where you think it would fit and send in a patch, see
    http://perl.apache.org/contribute/sv...rking_with_SVN on
    how to get the source.

    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


  11. Re: sethandlers question


    Torsten Foertsch wrote:
    [...]
    >
    > The apache-way to do this has a name: ErrorDocument or in mod_perl
    > $r->custom_response. Configure an ErrorDocument for 403 and return
    > HTTP_FORBIDDEN in your A...Handler. That has the benefit that the 403
    > status is logged and that the browser (think about search engines) sees
    > it. But the custom response page must be larger than 512 bytes or
    > you'll encounter problems with IE.
    > If you don't care about that you can
    > use $r->internal_redirect. That is a bit less work to do for your
    > server.
    >


    At this moment, I cannot see clearly how the ErrorDocument solution
    would allow me to send back a login page created dynamically, as I need
    to do. I will look it up, but as a definitive solution for the time
    being I would prefer the $r->internal_redirect method, where I can see
    more clearly how to do this.

    But I still have some (hopefully) last questions, if you would be so kind :

    As I understand this, the internal_redirect() basically stops the
    current request, and replaces it in-place by a totally new request,
    except that in that new request, $r->prev will be set to the (original)
    request that did the redirect, right ?

    (So in the new request, I can still access the pnotes set by the
    original request, via $r->prev->pnotes()).

    For this new request, the cycle restarts right at the beginning, and
    runs through all the steps just as if this was a main request. Right ?

    Are there any other significant differences between this new request and
    the previous one that I should be very aware of (in a mod_perl/AAA
    context) ?

    One thing I do not really understand, is what happens to the original
    request, when it issues a call to $r->internal_redirect().
    Does the original request still run to completion, or does it "abort"
    right there ?
    Does Apache still return something to the browser for the original
    request, or is that completely replaced by whatever the new (redirected)
    request produces ?
    After the call to $r->internal_redirect(), should the original request
    still do something ? (like return Apache2::Const::?????) ?

    Thanks

    P.S.
    I have downloaded the Apache source, and looked at the code within
    httpd-2.x.y/server/request.c, but it is still a bit obscure to me,
    except in a very general sense. I kind of approximately follow the
    steps, but do not always understand aspects like why it re-does
    directory walks at several stages, nor can I see at all where mod_perl
    plugs in to that code.


  12. Re: sethandlers question

    On Tue 14 Oct 2008, André Warnier wrote:
    > At this moment, I cannot see clearly how the ErrorDocument solution
    > would allow me to send back a login page created dynamically, as I
    > need to do. *I will look it up, but as a definitive solution for the
    > time being I would prefer the $r->internal_redirect method, where I
    > can see more clearly how to do this.



    PerlAuthenHandler "sub { \
    return Apache2::Const::FORBIDDEN unless ...;
    }"
    ErrorDocument 403 /login



    SetHandler modperl
    # you still have to supply a login_form function that expects a
    # $r object.
    PerlResponseHandler "sub { \
    my $r=shift; \
    $r->content_type('text/html'); \
    $r->print(login_form($r->prev));
    return Apache2::Const::OK;
    }"


    Your A-handler returns 403. Instead of sending the standard FORBIDDEN
    page to the browser apache catches the error because of the
    ErrorDocument directive. "/login" looks like an URI. Hence apache will
    perform an internal redirect to it. "/login" is configured in the
    normal modperl-way.

    The browser will see an HTTP status of 403 (it will also be logged as
    403). But the message sent along will be the output of &login_form. And
    that is what the user will see. &login_form has access to the original
    request. So, it can pass the original URI in a hidden field.

    See also http://httpd.apache.org/docs/2.2/mod...#errordocument

    Instead of 403 you can also use 401 if you want to use
    http-authentication. That is the user will see a browser generated
    password box. But I doubt that is what you want.

    > But I still have some (hopefully) last questions, if you would be so
    > kind :
    >
    > As I understand this, the internal_redirect() basically stops the
    > current request, and replaces it in-place by a totally new request,
    > except that in that new request, $r->prev will be set to the
    > (original) request that did the redirect, right ?


    Yes. Best if you return OK from the current handler right after the
    $r->internal_redirect line.

    > (So in the new request, I can still access the pnotes set by the
    > original request, via $r->prev->pnotes()).


    Yes.

    > For this new request, the cycle restarts right at the beginning, and
    > runs through all the steps just as if this was a main request. Right
    > ?


    AAA are possibly skipped as I mentioned before.

    > Are there any other significant differences between this new request
    > and the previous one that I should be very aware of (in a
    > mod_perl/AAA context) ?


    You'll find some, ;-)

    > One thing I do not really understand, is what happens to the original
    > request, when it issues a call to $r->internal_redirect().
    > Does the original request still run to completion, or does it "abort"
    > right there ?


    I think you'll see the original request again in the logging phase.

    > Does Apache still return something to the browser for the original
    > request, or is that completely replaced by whatever the new
    > (redirected) request produces ?


    No, not unless you have sent something prior to the internal_redirect.

    > After the call to $r->internal_redirect(), should the original
    > request still do something ? (like return Apache2::Const::?????) ?


    OK, see
    http://perl.apache.org/docs/2.0/api/...rnal_redirect_

    > P.S.
    > I have downloaded the Apache source, and looked at the code within
    > httpd-2.x.y/server/request.c, but it is still a bit obscure to me,
    > except in a very general sense. *I kind of approximately follow the
    > steps, but do not always understand aspects like why it re-does
    > directory walks at several stages, nor can I see at all where
    > mod_perl plugs in to that code.


    great! Many treasures are hidden there.

    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


  13. Re: sethandlers question

    On Tue 14 Oct 2008, Torsten Foertsch wrote:
    > On Tue 14 Oct 2008, André Warnier wrote:
    > > When I try this, I get an Apache error with the following logfile
    > > message : [Tue Oct 14 16:10:40 2008] [error] [client
    > > 84.158.163.207] $r->add_config() has failed: SetHandler not allowed
    > > here at /usr/local/lib/apache2/perllib/AUTH/StarLogCookie.pm line
    > > 414.\n

    >
    > That is an apache error. SetHandler needs the FileInfo override flag,
    > see http://httpd.apache.org/docs/2.2/mod...tml#sethandler. So,
    > the correct command would be:
    >
    > $r->add_config(['SetHandler ...'], Apache2::Const::OR_FILEINFO)
    >
    > or simpler
    >
    > $r->add_config(['SetHandler ...'], ~0)
    >
    > (since you know what directive you are adding).


    Maybe others are interested too, here are 2 private messages:

    On Wed 15 Oct 2008, André Warnier wrote:
    > Ok, I did, and it seems to work too :
    >
    > So I have 2 sequences that work :
    > a)
    > $r->add_config(['SetHandler modperl'], ~0);
    > $r->set_handlers(PerlAuthzHandler => []); # disable authorization
    > $r->set_handlers(PerlResponseHandler => \&_send_login_form);
    > #$r->set_handlers(PerlFixupHandler => sub {
    > $_[0]->handler('modperl') } );
    >
    > b)
    > #$r->add_config(['SetHandler modperl'], ~0);
    > $r->set_handlers(PerlAuthzHandler => []); # disable authorization
    > $r->set_handlers(PerlResponseHandler => \&_send_login_form);
    > $r->set_handlers(PerlFixupHandler => sub {
    > $_[0]->handler('modperl') } );
    >
    > Now, can you explain ?
    > I don't even understand what "~0" means..


    On Wed 15 Oct 2008, Torsten Foertsch wrote:
    > On Wed 15 Oct 2008, André Warnier wrote:
    > > 1) you mentioned that it was due to a Apache bug.

    >
    > Did I really say bug? I meant an Apache error message. You'll see the
    > same message if you try something like that:
    >
    >
    > AllowOverride AuthConfig
    >

    >
    > and then have an .htaccess with a SetHandler directive in it.
    > SetHandler needs "AllowOverride FileInfo". But only AuthConfig is
    > set.
    >
    > The 2nd parameter to add_config is a AllowOverride bit field. It
    > limits what kind of directives are allowed to be added. Think of it
    > as if you have read the directives from an untrusted source (like
    > .htaccess).
    >
    > > 2) I do not have a clue why the above would work around that bug.

    >
    > Apache wants here not only to be told to add the SetHandler but also
    > to be ensured "Yes, that is what I want. Just do it!".
    >
    > ~0 means all bits turned on.


    Torsten

    --
    Need professional mod_perl support?
    Just hire me: torsten.foertsch@gmx.net


+ Reply to Thread