[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mason
Subject:    [Mason] Re: Parameter out_method, ApacheHandler
From:       asjo () koldfront ! dk (Adam =?iso-8859-1?Q?Sj=F8gren?=)
Date:       2005-02-20 15:55:44
Message-ID: 87hdk78bun.fsf () koldfront ! dk
[Download RAW message or body]

On Sun, 13 Feb 2005 21:30:22 -0800, Jonathan wrote:

> You're right, ApacheHandler unconditionally sets out_method. I don't
> think we ever anticipated this need.

> What's the reason for setting out_method in conjunction with Apache? 
> As opposed to just using Interp like the original system did?

I wasn't able to create my own Interp with 1.26 - Mason complains
about a method not being present (specifics below).

Here's a minimal example that show what I do in 1.04 (apt-get install
libhtml-mason-perl/stable on Debian):

,----[ httpd-1.04.conf ]
> ServerName localhost
> 
> ServerType standalone
> Port 2345
> 
> User www-data
> Group www-data
> 
> ServerRoot /tmp/mason-test/apache-perl
> PidFile /tmp/mason-test/run/apache-perl.pid
> 
> Include /tmp/mason-test/apache-perl/modules.conf
> 
> ErrorLog /tmp/mason-test/log/error.log
> TransferLog /tmp/mason-test/log/access.log
> 
> PerlWarn on
> PerlFreshRestart Off
> PerlRequire /tmp/mason-test/apache-perl/httpd-1.04.pl
> 
> NameVirtualHost *
> 
> <VirtualHost *>
> DocumentRoot /tmp/mason-test/docs/
> SetHandler perl-script
> PerlHandler Mason104Test::handler
> </VirtualHost>
`----

,----[ httpd-1.04.pl ]
> package Mason104Test;
> 
> use strict;
> use warnings;
> 
> use Apache::Request;
> use Apache::File; # set_content_length
> use Apache::Constants qw(:response);
> 
> use HTML::Mason;
> use HTML::Mason::ApacheHandler (args_method=>'mod_perl');
> 
> my $httpd_user = scalar(getpwnam 'www-data');
> my $httpd_group = scalar(getgrnam 'www-data');
> 
> my $capture='';
> 
> my $parser=HTML::Mason::Parser->new(in_package=>'Mason104Test');
> my $interp=HTML::Mason::Interp->new(
> parser=>$parser,
> comp_root=>'/tmp/mason-test/docs/',
> data_dir=>'/tmp/mason-test/var/',
> out_mode=>'batch',
> out_method=>\$capture,
> );
> 
> my $handler=HTML::Mason::ApacheHandler->new(
> interp=>$interp,
> apache_status_title=>'HTML::Mason: Mason104Test',
> decline_dirs=>0,
> auto_send_headers=>0,
> );
> 
> chown ($httpd_user, $httpd_group, $interp->files_written);
> 
> 
> sub handler ($$) {
> my ($req)=@_;
> 
> my $r=Apache::Request->new($req);
> $r->parse;
> 
> my $status = $handler->handle_request($r);
> 
> $r->header_out('X-Mason-Version', $HTML::Mason::VERSION);
> 
> $r->status($status) if ($status ne OK);
> $r->set_content_length(length($capture));
> $r->send_http_header;
> 
> $r->print(\$capture);
> 
> $capture='';
> 
> return $status;
> }
> 
> 1;
`----

(Full file layout for the test listed below[1]).

Starting Apache (just one instance, don't daemonize):

 $ /usr/sbin/apache-perl -X -f /tmp/mason-test/apache-perl/httpd-1.04.conf

A test-request then goes like this:

 $ echo -e "GET /index.html HTTP/1.0\nHost: localhost\n\n" | nc localhost 2345
 HTTP/1.1 200 OK
 Date: Sun, 20 Feb 2005 15:22:52 GMT
 Server: Apache/1.3.33 (Debian GNU/Linux) mod_perl/1.29
 X-Mason-Version: 1.04
 Content-Length: 18
 Connection: close
 Content-Type: text/html

 Mason test: 2+2=4
 $ 

Here's what happens if I use that same code with 1.26 (apt-get install
libhtml-apache-perl/unstable on Debian):

 $ /usr/sbin/apache-perl -X -f /tmp/mason-test/apache-perl/httpd-1.04.conf
 [Sun Feb 20 16:26:50 2005] [error] The Parser module is no longer a part of \
HTML::Mason.  Please see the Lexer and Compiler modules, its \
replacements.\nCompilation failed in require at (eval 2) line 1.\n  Syntax error on \
line 19 of /tmp/mason-test/apache-perl/httpd-1.04.conf:  The Parser module is no \
longer a part of HTML::Mason.  Please see the Lexer and Compiler modules, its \
replacements.  Compilation failed in require at (eval 2) line 1.

 $ 

So, I make copies of httpd-1.04.conf and httpd-1.04.pl in
httpd-1.26.conf/pl and start modifying.

First error is using the Parser module as seen above. So I remove that
and put the in_class-argument into the Interp-creation[2].

Next error is 'out_mode' that Interp doesn't want anymore. I move it
to ApacheHandler. 'out_mode' isn't recognized there either, I remove
it totally.

Now I get to the error that made me stop trying to make my own Interp
object:

 $ /usr/sbin/apache-perl -X -f /tmp/mason-test/apache-perl/httpd-1.26.conf
 [Sun Feb 20 16:30:28 2005] [error] The resolver class your Interp object uses does \
not implement the 'apache_request_to_comp_path' method.  This means that \
ApacheHandler cannot resolve requests.  Are you using a handler.pl file created \
before version 1.10?  Please see the handler.pl sample that comes with the latest \
version of Mason.\nStack:\n  \
[/tmp/mason-test/apache-perl/httpd-1.26.pl:25]\nCompilation failed in require at \
(eval 2) line 1.\n  Syntax error on line 19 of \
/tmp/mason-test/apache-perl/httpd-1.26.conf:  The resolver class your Interp object \
uses does not implement the 'apache_request_to_comp_path' method.  This means that \
ApacheHandler cannot resolve requests.  Are you using a handler.pl file created \
before version 1.10?  Please see the handler.pl sample that comes with the latest \
version of Mason.  Stack:
   [/tmp/mason-test/apache-perl/httpd-1.26.pl:25]
 Compilation failed in require at (eval 2) line 1.

 $ 

This is what httpd-1.26.pl looks like at this point:

 package Mason126Test;

 use strict;
 use warnings;

 use Apache::Request;
 use Apache::File; # set_content_length
 use Apache::Constants qw(:response);

 use HTML::Mason;
 use HTML::Mason::ApacheHandler (args_method=>'mod_perl');

 my $httpd_user = scalar(getpwnam 'www-data');
 my $httpd_group = scalar(getgrnam 'www-data');

 my $capture='';

 my $interp=HTML::Mason::Interp->new(
                                     in_package=>'Mason126Test',
                                     comp_root=>'/tmp/mason-test/docs/',
                                     data_dir=>'/tmp/mason-test/var/',
                                     out_method=>\$capture,
                                    );

 my $handler=HTML::Mason::ApacheHandler->new(
                                             interp=>$interp,
                                             apache_status_title=>'HTML::Mason: \
Mason126Test',  decline_dirs=>0,
                                             auto_send_headers=>0,
                                            );

 chown ($httpd_user, $httpd_group, $interp->files_written);


 sub handler ($$) {
     my ($req)=@_;

     my $r=Apache::Request->new($req);
     $r->parse;

     my $status = $handler->handle_request($r);

     $r->header_out('X-Mason-Version', $HTML::Mason::VERSION);

     $r->status($status) if ($status ne OK);
     $r->set_content_length(length($capture));
     $r->send_http_header;

     $r->print(\$capture);

     return $status;
 }

 1;

So, I decide to not create my own Interp-object, as I have no idea of
why it doesn't have that apache_request_to_comp_path-method.

This is what I end up with, which also makes Apache/mod_perl/Mason
stop complaining:

 package Mason126Test;

 use strict;
 use warnings;

 use Apache::Request;
 use Apache::File; # set_content_length
 use Apache::Constants qw(:response);

 use HTML::Mason;
 use HTML::Mason::ApacheHandler (args_method=>'mod_perl');

 my $capture='';

 my $handler=HTML::Mason::ApacheHandler->new(
                                             in_package=>'Mason126Test',
                                             comp_root=>'/tmp/mason-test/docs/',
                                             data_dir=>'/tmp/mason-test/var/',
                                             out_method=>\$capture,
                                             apache_status_title=>'HTML::Mason: \
Mason126Test',  decline_dirs=>0,
                                             auto_send_headers=>0,
                                            );

 sub handler ($$) {
     my ($req)=@_;

     my $r=Apache::Request->new($req);
     $r->parse;

     my $status = $handler->handle_request($r);

     $r->header_out('X-Mason-Version', $HTML::Mason::VERSION);

     $r->status($status) if ($status ne OK);
     $r->set_content_length(length($capture));
     $r->send_http_header;

     $r->print(\$capture);

     return $status;
 }

 1;

(Much more readable than the 1.04 version, incidently).

But out_method is ignored, resulting in the headers being output *after*
the content:

 $ echo -e "GET /index.html HTTP/1.0\nHost: localhost\n\n" | nc localhost 2345
 Mason test: 2+2=4
 HTTP/1.1 200 OK
 Date: Sun, 20 Feb 2005 15:33:16 GMT
 Server: Apache/1.3.33 (Debian GNU/Linux) mod_perl/1.29
 X-Mason-Version: 1.26
 Content-Length: 0
 Connection: close
 Content-Type: text/html

 $ 

Which of course isn't good.

The patch I posted earlier "fixes" this, but only when out_method is a
scalar-ref:

 $ echo -e "GET /index.html HTTP/1.0\nHost: localhost\n\n" | nc localhost 2345
 HTTP/1.1 200 OK
 Date: Sun, 20 Feb 2005 15:35:55 GMT
 Server: Apache/1.3.33 (Debian GNU/Linux) mod_perl/1.29
 X-Mason-Version: 1.26
 Content-Length: 18
 Connection: close
 Content-Type: text/html

 Mason test: 2+2=4
 $ 


What this minimal example doesn't show is *why* I want to capture
Masons output, only that out_method stopped working for me (or that
I'm doing something wrong with 1.26).


In the CMS I'm doing this for, Mason is (ab)used as a super-powered
template system.

The system has a split in three parts: admin, common and public, where
a set of component roots, mason-components and perl-modules for each
generate their part of the page.

The common-part is shared between admin and public (showing the
"content" of a page both to website-users and administration-users),
so the CMS needs to capture the output of a "Mason-run", but the
niceties of $r and so on are still wanted in the components.

Maybe there are better ways to do this (there are certainly a lot of
ways), but this is what is needed for this application.


  Best regards,

    Adam

[1]:

,----[ ls /tmp/mason-test/* ]
> /tmp/mason-test/apache-perl:
> httpd-1.04.conf
> httpd-1.04.pl
> httpd-1.26.conf
> httpd-1.26.pl
> modules.conf
> 
> /tmp/mason-test/docs:
> index.html
> 
> /tmp/mason-test/log:
> access.log
> error.log
> 
> /tmp/mason-test/run:
> apache-perl.pid
> 
> /tmp/mason-test/var:
> cache
> debug
> etc
> obj
> preview
`----

index.html is just:

,----[ index.html ]
> Mason test: 2+2=<% 2+2 %>
`----

[2]: Maybe this is my mistake - I need different objects for different
     websites (virtual hosts) in the large, non-minimal application,
     though.


P.S. Sorry for taking so long in following up on this. And for this
     being so long.


-- 
 "There are some stunningly novel ideas in Perl, for          Adam Sjøgren
  example. Many are stunningly bad, but that's always    asjo@koldfront.dk
  true of ambitious efforts."



-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Mason-users mailing list
Mason-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mason-users


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic