Custom PerlResponseHandler for a subrequest

2024-06-04 Thread Jan Kasprzak
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

2024-06-04 Thread Jan Pazdziora
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

2024-06-04 Thread Jan Kasprzak
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