Custom PerlResponseHandler for a subrequest
Hello, I am trying to do something like this in PerlAuthenHandler, and it mostly works: sub auth_handler { my ($r) = @_; ... if ($cond) { $r->set_handlers(PerlResponseHandler => sub { my ($r) = @_; $r->content_type('text/plain'); $r->print("custom handler was here\n"); return Apache2::Const::OK; }); $r->user('dummy-user-for-a-dummy-handler'); return Apache2::Const::OK; } ... } when $cond happens, I get 200 OK with "custom handler was here" instead of whatever is configured as PerlResponseHandler in httpd.conf. So far good. However, when I add mod_rewrite to the mix, it stops working. I want to allow URLs without .pl at the end to be handled by the same .pl script (I only added the Rewrite... directives, the rest was already in httpd.conf): RewriteCond %{REQUEST_FILENAME} !-d # skip directories RewriteCond %{REQUEST_FILENAME} !-f # skip existing files RewriteCond %{REQUEST_FILENAME}.pl -f # .pl exists, use it instead RewriteRule (.*) $1.pl [L] SetHandler perl-script PerlResponseHandler My::Ordinary::Handler Then for requests meeting $cond above I get the following: https://example.com/directory -> 302 to /directory/ (trailing slash, OK) https://example.com/directory/ -> 200 with custom handler as expected https://example.com/directory/index.pl -> 200 with custom handler as expected https://example.com/directory/index -> 200 from My::Ordinary::Handler - FAIL https://example.com/directory/foo.pl -> 200 with custom handler as expected https://example.com/directory/foo -> 200 from My::Ordinary::Handler - FAIL It seems that the auth_handler gets called for all the above requests, but for the failed ones mod_rewrite creates subrequests, which do not inherit the custom PerlResponseHandler set by auth_handler(). How can I replace a PerlResponseHandler even for a subrequest? Or how can I tap to a subrequest creation? Or how can I bypass mod_rewrite from within the PerlAuthenHandler and return my own 200 OK response immediately? Thanks, -Yenya -- | Jan "Yenya" Kasprzak | | https://www.fi.muni.cz/~kas/GPG: 4096R/A45477D5 | We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise. --Larry Wall
Re: Custom PerlResponseHandler for a subrequest
On Tue, Jun 04, 2024 at 03:35:06PM +0200, Jan Kasprzak wrote: > Hello, > > I am trying to do something like this in PerlAuthenHandler, > and it mostly works: > > sub auth_handler { > my ($r) = @_; > ... > if ($cond) { > $r->set_handlers(PerlResponseHandler => sub { > my ($r) = @_; > $r->content_type('text/plain'); > $r->print("custom handler was here\n"); > return Apache2::Const::OK; > }); > $r->user('dummy-user-for-a-dummy-handler'); > return Apache2::Const::OK; > } > ... > } > > when $cond happens, I get 200 OK with "custom handler was here" > instead of whatever is configured as PerlResponseHandler in httpd.conf. > So far good. [...] > Then for requests meeting $cond above I get the following: > > https://example.com/directory -> 302 to /directory/ (trailing slash, OK) > https://example.com/directory/ -> 200 with custom handler as expected > https://example.com/directory/index.pl -> 200 with custom handler as expected > https://example.com/directory/index -> 200 from My::Ordinary::Handler - FAIL > https://example.com/directory/foo.pl -> 200 with custom handler as expected > https://example.com/directory/foo -> 200 from My::Ordinary::Handler - FAIL > > It seems that the auth_handler gets called for all the above requests, > but for the failed ones mod_rewrite creates subrequests, which do not inherit > the custom PerlResponseHandler set by auth_handler(). How can I replace > a PerlResponseHandler even for a subrequest? Or how can I tap to a subrequest > creation? Or how can I bypass mod_rewrite from within the PerlAuthenHandler > and return my own 200 OK response immediately? Are you able to check / configure some logging to see if that auth_handler was called at all in the redirect / subrequest case, and if the $cond was found true there? Do you still see the dummy-user-for-a-dummy-handler logged (with My::Ordinary::Handler content), or is that user information missing as well? How is that auth_handler configured / enabled anyway? -- Jan Pazdziora
Re: Custom PerlResponseHandler for a subrequest
Hi Jan, Jan Pazdziora wrote: > On Tue, Jun 04, 2024 at 03:35:06PM +0200, Jan Kasprzak wrote: > > Hello, > > > > I am trying to do something like this in PerlAuthenHandler, > > and it mostly works: > > > > sub auth_handler { > > my ($r) = @_; > > ... > > if ($cond) { > > $r->set_handlers(PerlResponseHandler => sub { > > my ($r) = @_; > > $r->content_type('text/plain'); > > $r->print("custom handler was here\n"); > > return Apache2::Const::OK; > > }); > > $r->user('dummy-user-for-a-dummy-handler'); > > return Apache2::Const::OK; > > } > > ... > > } > > > > when $cond happens, I get 200 OK with "custom handler was here" > > instead of whatever is configured as PerlResponseHandler in httpd.conf. > > So far good. > > [...] > > > Then for requests meeting $cond above I get the following: > > > > https://example.com/directory -> 302 to /directory/ (trailing slash, OK) > > https://example.com/directory/ -> 200 with custom handler as expected > > https://example.com/directory/index.pl -> 200 with custom handler as > > expected > > https://example.com/directory/index -> 200 from My::Ordinary::Handler - FAIL > > https://example.com/directory/foo.pl -> 200 with custom handler as expected > > https://example.com/directory/foo -> 200 from My::Ordinary::Handler - FAIL > > > > It seems that the auth_handler gets called for all the above requests, > > but for the failed ones mod_rewrite creates subrequests, which do not > > inherit > > the custom PerlResponseHandler set by auth_handler(). How can I replace > > a PerlResponseHandler even for a subrequest? Or how can I tap to a > > subrequest > > creation? Or how can I bypass mod_rewrite from within the PerlAuthenHandler > > and return my own 200 OK response immediately? > > Are you able to check / configure some logging to see if that > auth_handler was called at all in the redirect / subrequest case, > and if the $cond was found true there? There is a difference between Apache 2.2 and 2.4. In 2.2, I was able to return Apache2::Const::OK from the PerlAuthenHandler, but 2.4 refuses to do this unless I set $r->user() to a non-empty value. And if I do this, the PerlAuthenHandler is not called in a subrequest, because the user is already authenticated. > Do you still see the dummy-user-for-a-dummy-handler logged (with > My::Ordinary::Handler content), or is that user information missing > as well? Yes, in My::Ordinary::Handler, $r->user() is set to dummy-user-for-a-dummy-handler. > How is that auth_handler configured / enabled anyway? Something like AuthType My::AuthModule PerlAuthenHandler My::AuthModule->auth_handler require valid-user It seems that I was able to work around this problem the following way: sub auth_handler { ... if ($cond) { $r->content_type('text/plain'); $r->custom_response(Apache2::Const::HTTP_OK => "custom handler was here\n"); return Apache2::Const::HTTP_OK; } } This way I return the 200 OK with my own body directly from auth_handler() instead of overriding the PerlResponseHandler. There is a slight difference that this returns 200 OK even for non-existent paths, but I can live with that. However, I would still be interested in figuring out how to override PerlResponseHandler for mod_rewrite subrequests. Cheers, -Yenya -- | Jan "Yenya" Kasprzak | | https://www.fi.muni.cz/~kas/GPG: 4096R/A45477D5 | We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise. --Larry Wall