Mailing List Archive

Tutorial Fails under Apache Mod_Perl
Perl Catalyst Problem

Hi all,

I have a bit of a problem with Catalyst. I have been working through the Catalyst tutorial as found at http://search.cpan.org/~ether/Catalyst-Manual-5.9007/lib/Catalyst/Manual/Tutorial.pod . First off, this is a very good introduction to Catalyst development. I have completed chapters 0 to 8, and the code that I have entered works flawlessly when run using the myapp_server.pl. this was initally done on the provided Catalyst tutorial virtual machine image downloaded from http://cattut.shadowcat.co.uk/.

I have since moved this to my own development server, and it also works flawlessly when using the myapp_server.pl script on the new computer.

My problem is that, the exact same code, running on the exact same development computer, blows up when running as a mod_perl module under Apache. When I attempt to log in, I get the following error:
    Caught exception in MyApp::Controller::Login->index "Can't use string
     ("Catalyst::Authentication::Store:"...) as a HASH ref while "strict
     refs" in use at accessor Catalyst::Authentication::Store::DBIx::Class
     ::User::_user (defined at /usr/share/perl5/Catalyst/Authentication/
     Store/DBIx/Class/User.pm line 12) line 5, <DATA> line 1000."

The stack trace points the failure at the line where the $c->authenticate method is called:
   35:     if ($username && $password) {
   36:         # Attempt to log the user in
   37:         $c->log->debug("value in \$c->authenticate is \"".Dumper($c)."\"");
   38:         if ($c->authenticate({ username => $username,
   39:                                password => $password  } )) {
   40:             # If successful, then let them use the application
   41:             $c->response->redirect($c->uri_for(

if i add a debug or print statement before this. the error moves to the first place where I reference the $c context object.

Again, this exact same code works with no problem when run using the myapp_server.pl. this is the only difference, the host name is the same, the ip address is the same, the code is the same, the installed perl libraries are the same, the difference in the url is one is accessed using port 3000 and the other is  at port 80 (http://mytest.org:3000/ vs http://mytest.org/ ).

My environment:
My web development server is runnung Ubuntu 13.10 Server in a Virtualbox VM.
I have downloaded and installed Catalyst mostly using the packages available in the Ubuntu 13.10 repositories, although a small hand full of perl modules used by the tutorial Catalyst had to be installed via CPAN using the Catalyst project Makefile. except for a couple of PHP modules and the Catalyst stuff, this is a fresh, vanilla install of Ubuntu 13.10, choosing to install the LAMP, SSH server, and Mail Server package groups during the installation.

The apache2 configuration file, enabling the site under mod_perl on apache:
   $ cat /etc/apache2/sites-enabled/004-osws-catalyst-site.conf
   PerlSwitches    -I/home/onestopw/lib
   PerlModule      MyApp

   <VirtualHost mytest.org:80>
        # The ServerName directive sets the request scheme, hostname and port that
        # the server uses to identify itself. This is used when creating
        # redirection URLs. In the context of virtual hosts, the ServerName
        # specifies what hostname must appear in the request's Host: header to
        # match this virtual host. For the default virtual host (this file) this
        # value is not decisive as it is used as a last resort host regardless.
        # However, you must set it for any further virtual host explicitly.
        ServerName osws.org

        ServerAdmin webmaster@localhost
        DocumentRoot /home/onestopw/root

        # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
        # error, crit, alert, emerg.
        # It is also possible to configure the loglevel for particular
        # modules, e.g.
        #LogLevel info ssl:warn

        ErrorLog  /home/onestopw/logs/error.log
        CustomLog /home/onestopw/logs/access.log combined

        # For most configuration files from conf-available/, which are
        # enabled or disabled at a global level, it is possible to
        # include a line for only one particular virtual host. For example the
        # following line enables the CGI configuration for this host only
        # after it has been globally disabled with "a2disconf".
        #Include conf-available/serve-cgi-bin.conf

        # run the app from the site root directory
        <Location />
                SetHandler              modperl
                PerlResponseHandler     MyApp
                #Options Indexes FollowSymLinks
                Order Deny,Allow
                Allow from all
                Require all granted
        </Location>

        # however, server static content with apache alone
        <Location /static>
                SetHandler              default-handler
        </Location>


   </VirtualHost>

   # vim: syntax=apache ts=4 sw=4 sts=4 sr noet

this apache.conf file was modeled on the file described at http://search.cpan.org/~flora/Catalyst-Engine-Apache-1.16/lib/Catalyst/Engine/Apache2/MP20.pm

the site starts to work under apache mod_perl and the login page is displayed whenever any url to this site is loaded. this is also exactly what happens when run using the myapp_server.pl when no user is logged in. When I supply a user name and password on the login form and submit the form, that is when the above error occurs when running under mod_perl. When run by the myapp_server.pl script, submitting the form validates the user and password, and if valid, displays the book list page.

I believe that this error is caused by the Catalyst object not being properly blessed when running as a mod_perl module. This means that when the authenticate method is called, instead of $c being a context object with an authenticate method, it is simply a string containing "Catalyst::Authentication::Store:", the name of the object type that it is supposed to be.
 
At this point, I am at a loss. Something is different between the apache mod_perl environment and the myapp_server.pl environment. I am currently stepping through the execution of loading and configuration of the MyApp module, placing print STDERR lines throughout the Catalyst modules as MyApp.pm is loaded. Hopefully, the difference will become apparent, but if anyone more familiar with the inner workings of Catalyst sees something obvious, please let me know.

My project is stuck in the mud at this point, since there would be no point in developing it using Catalyst if Catalyst will not actually work under apache.

Thanks,

William Anderson
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
Hi all,

I found the cause of my problems.


While chasing down the bug into Catalyst::Authentication::Credential::Password,
I find that this creates a user object via $realm->find_user($userfindauthinfo, $c);
this is a Catalyst::Authentication::Realm::SimpleDB, with a hashref appened
to it. The object is returned if a matching user is found, and undef is
returned if no matching user is found.


Note that while doing this, I first logged out of the test site with port 3000,
and logged back in successfully. I then reloaded the root url for the
"production" site at port 80, and found that I was logged in. I then went to the
/books/list page, and was rewarded with a different crash:
    DBIx::Class::Storage::DBI::catch {...} (): DBI Connection failed:
    DBI connect('myapp.db','',...) failed: unable to open database file
    at /usr/share/perl5/DBIx/Class/Storage/DBI.pm line 1395. at
    /home/onestopw/lib/MyApp/Controller/Books.pm line 44

Ah Ha!! The root of my problem is the PWD value, and the location where
the application will look for the files that it is supposed to use. The script myapp_server.pl inherits the PWD from the shell it is run from.

And its that simple!!! apache mod_perl has a different PWD value, and it was not
finding the database file. Rather then crashing outright when this error occurs
the Catalyst MyApp ran until the model objects tried to access the database and, because the file could not be found, crashing in wierd and hard to debug ways.

To fix, simply specify the full file system path to the myapp.db file. This is likely to be a problem with ALL filesystem objects that the application wants to use.

This simple, stupid, problem could be avoided if, during startup Catalyst checks to see if we can actually see, open, touch the database (file or server), and if not, fail in some way that makes it obvious that it can not see the database. Actually, I would go so far to say that this is a bug and that this should  be fixed it Catalyst. 


Anyway, I love open source sofware because I can dig in and fix problems like this without calling the vendor's technical support.

Thank You,

William


________________________________
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
It sounds like the app's no longer running in a distribution directory
(containing a Makefile.PL)
see the docs for the "-HOME" switch for how to handle this:
http://search.cpan.org/~jjnapiork/Catalyst-Runtime-5.90051/lib/Catalyst.pm#-Home
Carl

On 5 December 2013 20:11, William Anderson <william_anderson@yahoo.com> wrote:
> Hi all,
>
> I found the cause of my problems.
>
> While chasing down the bug into
> Catalyst::Authentication::Credential::Password,
> I find that this creates a user object via
> $realm->find_user($userfindauthinfo, $c);
> this is a Catalyst::Authentication::Realm::SimpleDB, with a hashref appened
> to it. The object is returned if a matching user is found, and undef is
> returned if no matching user is found.
>
> Note that while doing this, I first logged out of the test site with port
> 3000,
> and logged back in successfully. I then reloaded the root url for the
> "production" site at port 80, and found that I was logged in. I then went to
> the
> /books/list page, and was rewarded with a different crash:
> DBIx::Class::Storage::DBI::catch {...} (): DBI Connection failed:
> DBI connect('myapp.db','',...) failed: unable to open database file
> at /usr/share/perl5/DBIx/Class/Storage/DBI.pm line 1395. at
> /home/onestopw/lib/MyApp/Controller/Books.pm line 44
>
> Ah Ha!! The root of my problem is the PWD value, and the location where
> the application will look for the files that it is supposed to use. The
> script myapp_server.pl inherits the PWD from the shell it is run from.
>
> And its that simple!!! apache mod_perl has a different PWD value, and it was
> not
> finding the database file. Rather then crashing outright when this error
> occurs
> the Catalyst MyApp ran until the model objects tried to access the database
> and, because the file could not be found, crashing in wierd and hard to
> debug ways.
>
> To fix, simply specify the full file system path to the myapp.db file. This
> is likely to be a problem with ALL filesystem objects that the application
> wants to use.
>
> This simple, stupid, problem could be avoided if, during startup Catalyst
> checks to see if we can actually see, open, touch the database (file or
> server), and if not, fail in some way that makes it obvious that it can not
> see the database. Actually, I would go so far to say that this is a bug and
> that this should be fixed it Catalyst.
>
> Anyway, I love open source sofware because I can dig in and fix problems
> like this without calling the vendor's technical support.
>
> Thank You,
>
> William
> ________________________________
>
>
> _______________________________________________
> Catalyst-dev mailing list
> Catalyst-dev@lists.scsys.co.uk
> http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
>

_______________________________________________
Catalyst-dev mailing list
Catalyst-dev@lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
Hi,

Application is not running in a distribution directory. Well, yes the base directory that the application was running in moved when I moved it to the actual web server, i.e, moved from /home/catalyst on the tutorial virtual machine to /home/testsite on the test web server virtual machine.

However, the whole contents of the Catalyst project was moved, including the Makefile.pl and the generated Makefile. Also, I ran perl Makefile.pl and make several times while i found and installed the perl modules that were not included in any Ubuntu packages. Should this not have updated the paths?

Anyway, there must be a method where you can take a Catalyst application, developed using the development server script, and deploy it onto an actual web server that does not cause such problems. I will continue reading, experimenting, and learning about Catalyst.

Thank you for your help,

William




________________________________
From: Carl Franks <carl@fireartist.com>
To: Development of the elegant MVC web framework <catalyst-dev@lists.scsys.co.uk>
Sent: Thursday, December 5, 2013 3:04 PM
Subject: Re: [Catalyst-dev] Tutorial Fails under Apache Mod_Perl


It sounds like the app's no longer running in a distribution directory
(containing a Makefile.PL)
see the docs for the "-HOME" switch for how to handle this:
http://search.cpan.org/~jjnapiork/Catalyst-Runtime-5.90051/lib/Catalyst.pm#-Home
Carl
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
mod_perl is not a great deployment target. You'd need a good reason to want to use it.

On 06/12/2013, at 9:51 AM, William Anderson wrote:

> Hi,
>
> Application is not running in a distribution directory. Well, yes the base directory that the application was running in moved when I moved it to the actual web server, i.e, moved from /home/catalyst on the tutorial virtual machine to /home/testsite on the test web server virtual machine.
>
> However, the whole contents of the Catalyst project was moved, including the Makefile.pl and the generated Makefile. Also, I ran perl Makefile.pl and make several times while i found and installed the perl modules that were not included in any Ubuntu packages. Should this not have updated the paths?
>
> Anyway, there must be a method where you can take a Catalyst application, developed using the development server script, and deploy it onto an actual web server that does not cause such problems. I will continue reading, experimenting, and learning about Catalyst.
>
> Thank you for your help,
>
> William
>
>
>
>
> ________________________________
> From: Carl Franks <carl@fireartist.com>
> To: Development of the elegant MVC web framework <catalyst-dev@lists.scsys.co.uk>
> Sent: Thursday, December 5, 2013 3:04 PM
> Subject: Re: [Catalyst-dev] Tutorial Fails under Apache Mod_Perl
>
>
> It sounds like the app's no longer running in a distribution directory
> (containing a Makefile.PL)
> see the docs for the "-HOME" switch for how to handle this:
> http://search.cpan.org/~jjnapiork/Catalyst-Runtime-5.90051/lib/Catalyst.pm#-Home
> Carl_______________________________________________
> Catalyst-dev mailing list
> Catalyst-dev@lists.scsys.co.uk
> http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev


_______________________________________________
Catalyst-dev mailing list
Catalyst-dev@lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
Hi,

What would be a better target?

William Anderson




________________________________
From: Kieren Diment <diment@gmail.com>
To: Development of the elegant MVC web framework <catalyst-dev@lists.scsys.co.uk>
Sent: Thursday, December 5, 2013 3:55 PM
Subject: Re: [Catalyst-dev] Tutorial Fails under Apache Mod_Perl


mod_perl is not a great deployment target.  You'd need a good reason to want to use it.
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
Fastcgi or reverse proxy.

On 06/12/2013, at 10:03 AM, William Anderson wrote:

> Hi,
>
> What would be a better target?
>
> William Anderson
>
>
>
>
> ________________________________
> From: Kieren Diment <diment@gmail.com>
> To: Development of the elegant MVC web framework <catalyst-dev@lists.scsys.co.uk>
> Sent: Thursday, December 5, 2013 3:55 PM
> Subject: Re: [Catalyst-dev] Tutorial Fails under Apache Mod_Perl
>
>
> mod_perl is not a great deployment target. You'd need a good reason to want to use it._______________________________________________
> Catalyst-dev mailing list
> Catalyst-dev@lists.scsys.co.uk
> http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev


_______________________________________________
Catalyst-dev mailing list
Catalyst-dev@lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
RE: Tutorial Fails under Apache Mod_Perl [ In reply to ]
Hi William,

I have found deployment on different machines definitely raises some issues, and I feel like there are some best practices.

If you can I would say skip the sqlite and go straight for a mysql database. I believe there are converters that can convert your schema and input your data. Then your connection data will always be the same and you won't have to deal with file paths.

File paths in general are a pain with deployment. Either avoid them or see if you can have a setup where you have a filesystem that is shared between your development and production machines.

In any case your testing is better served by either using the catalyst testing suite (which is very comprehensive!), a git post hook, or both.

Static content! If you are going to have multiple applications sharing the same domain you do not want the usual MyApp/root/static, but instead something like MyApp/root/myapp/static. Then if you deploy using apache you will have something like:

Alias /myapp1/static /var/www/MyApp1/root/myapp1/static
<Directory /var/www/MyApp1/root/static>
Options Includes FollowSymlinks Indexes
Order allow,deny
Allow from all
</Directory>

Alias /myapp2/static /var/www/MyApp2/root/myapp2/static
<Directory /var/www/MyApp2/root/static>
Options Includes FollowSymlinks Indexes
Order allow,deny
Allow from all
</Directory>

And in your application your urls will look like : $c.uri_for("/myapp/static/file.css"). In fact I wish this would be changed when the original skeleton is built using catalyst.pl MyApp.

This is probably not applicable if you prefer to have all of your static content served out of your apache document root, but I prefer to keep mine on a per application basis and keep the whole thing under version control.

I have also found deployment to be MUCH, MUCH easier since I setup my environment so my development and production matched each other almost exactly. This is especially true if you are using javascript libraries. Not everyone writes their code so it knows when the path is being prefixed by something else, and often I have had to go in there and hardcode the url. We have productions set up with Apache and FastCGI, and use Catalyst::TraitFor::Request::ProxyBase.

If you are using SSL and want your path prefixed by /myapp (www.example.com/myapp1/stuff) your apache config should look something like this for development.

(This really took some doing to figure out. Is there any way it could be put into the catalyst wiki?)

#DEVELOPMENT
<VirtualHost *:443>
ProxyRequests On
ProxyVia On
ProxyReceiveBufferSize 16384
ProxyPass /myapp/static !
Alias /myapp/static /var/www/MyApp/root/myapp/static

<Location /myapp>
# You must have mod_headers enabled for that
# RequestHeader set X-Request-Base /preview
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1

SSLRequireSSL
SetHandler perl-script
RequestHeader set X-URL-SCHEME https
RequestHeader set X-Request-Base https://development.com/myapp
</Location>

ProxyPass /myapp http://localhost:3000
ProxyPassReverse /myapp http://localhost:3000
</VirtualHost>


#PRODUCTION
Alias /myapp/static /var/www/MyApp/root/myapp/static
<Directory /var/www/MyApp/root/myapp/static>
Options Includes FollowSymlinks Indexes
Order allow,deny
Allow from all
</Directory>

Alias /myapp /var/www/MyApp/script/myapp_fastcgi.pl/
<Directory /var/www/MyApp/script/>
SetHandler fcgid-script
Options +ExecCGI
# Customize the next two directives for your requirements.
Order allow,deny
Allow from all
</Directory>

I really love developing in catalyst in any case, even if this stuff was a bit hard to figure out.

If you are using Ubuntu as your production server you need to enable the fastcgi and suexec modules as well.

The only other 'big' thing I have done is I no longer keep my model logic within the application because I have several applications that use the same database and do many of the same things. Instead I h2xs to create myself a perl module skeleton. In this case it is AdvComp-AdminModel. Then cd to that directory and run the following

perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:./lib -e 'make_schema_at("AdvComp::AdminModel", { debug => 1 }, [ "dbi:mysql:administrationdb:mysqlhost.com","user", "password" ])'

Then in your Model/ADMIN.pm (I think the tutorial uses DB.pm or SCHEMA.pm or something).

package MyApp::Model::ADMIN;

use strict;

use lib "Path/to/AdvComp-AdminModel/lib";
use AdvComp::AdminModel;

use base 'Catalyst::Model::DBIC::Schema';

__PACKAGE__->config(
schema_class => 'AdvComp::AdminModel',

connect_info => {
dsn => 'dbi:mysql:administrationdb:mysqlhost.com',
user => 'user',
password => 'password',
AutoCommit => q{1},
}
);

Then your models will work as usual with $c->model('ADMIN::Table').

In general I find a lot of my apps are doing at least a few common things, and instead of keeping that login in the controller or even in a Moose role I have a separate module (created with h2xs again) called Web::Worker, and in that I add the common things I need. Only url mapping and things unique to the application stay within the catalyst structure.

I hope it goes without saying all my separate perl modules/models are under version control as well!

Happy coding!

Best,
Jillian

________________________________________
From: William Anderson [william_anderson@yahoo.com]
Sent: Friday, December 06, 2013 1:51 AM
To: Development of the elegant MVC web framework
Subject: Re: [Catalyst-dev] Tutorial Fails under Apache Mod_Perl
is is
Hi,

Application is not running in a distribution directory. Well, yes the base directory that the application was running in moved when I moved it to the actual web server, i.e, moved from /home/catalyst on the tutorial virtual machine to /home/testsite on the test web server virtual machine.

However, the whole contents of the Catalyst project was moved, including the Makefile.pl and the generated Makefile. Also, I ran perl Makefile.pl and make several times while i found and installed the perl modules that were not included in any Ubuntu packages. Should this not have updated the paths?

Anyway, there must be a method where you can take a Catalyst application, developed using the development server script, and deploy it onto an actual web server that does not cause such problems. I will continue reading, experimenting, and learning about Catalyst.

Thank you for your help,

William

________________________________
From: Carl Franks <carl@fireartist.com>
To: Development of the elegant MVC web framework <catalyst-dev@lists.scsys.co.uk>
Sent: Thursday, December 5, 2013 3:04 PM
Subject: Re: [Catalyst-dev] Tutorial Fails under Apache Mod_Perl

It sounds like the app's no longer running in a distribution directory
(containing a Makefile.PL)
see the docs for the "-HOME" switch for how to handle this:
http://search.cpan.org/~jjnapiork/Catalyst-Runtime-5.90051/lib/Catalyst.pm#-Home
Carl

_______________________________________________
Catalyst-dev mailing list
Catalyst-dev@lists.scsys.co.uk
http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst-dev
Re: Tutorial Fails under Apache Mod_Perl [ In reply to ]
Oh wow,

Thanks for the wealth of ideas.

William Anderson



________________________________