Difference between revisions of "Catalyst"
| Line 98: | Line 98: | ||
(note the trailing slash) results in a default welcome screen. (If the result is a 500, something wasn't set up correctly.) | (note the trailing slash) results in a default welcome screen. (If the result is a 500, something wasn't set up correctly.) | ||
| − | ==== | + | ====Well-hidden dispatch==== |
With the following methodology, it is possible to: | With the following methodology, it is possible to: | ||
| Line 107: | Line 107: | ||
=====Pre-flight===== | =====Pre-flight===== | ||
| − | + | * Ensure FastCGI is enabled on the domain. | |
| + | * Ensure that <code>dash</code>, or some other minimalist/low-overhead shell, is installed. | ||
| + | ** We will use a wrapper script rather than a symlink to run the project dispatch script. This way, the script is able to locate itself correctly. | ||
| + | * Ensure the CPAN module <code>Catalyst::TraitFor::Request::ProxyBase</code> is installed. | ||
| + | ** This module is used here to alter the base URI so that requests to the dispatch script cannot be made directly by the client. | ||
| − | + | =====Locations===== | |
| − | + | These variables are assumed set: | |
| − | + | <syntaxhighlight lang=bash> | |
| + | # The full path to dash (or your choice of minimal sh) | ||
| + | export DASH="$HOME/bin/dash" | ||
| + | # The name of the perlbrew env to use | ||
| + | export MYPERLENV=myperl | ||
| + | # The full path to the domain document root | ||
| + | export DOCUMENT_ROOT="$HOME/sub.example.com" | ||
| + | # The name of the Catalyst project | ||
| + | export PROJECT_NAME=Foo | ||
| + | # The root dir of the Catalyst project | ||
| + | export PROJECT_ROOT="$HOME/catalyst-projects/$PROJECT_NAME" | ||
| + | |||
| + | # The full path to main perl module for the Catalyst project | ||
| + | export PROJECT_MAIN_MODULE="$PROJECT_ROOT/lib/$PROJECT_NAME.pm" | ||
| + | # The full path to the FastCGI script for the Catalyst project | ||
| + | export PROJECT_FASTCGI_SCRIPT="`find "$PROJECT_ROOT/script/" -name '*_fastcgi.pl'`" | ||
| + | |||
| + | # The full path to the perl that should be used | ||
| + | export MYPERL="`perlbrew use "$MYPERLENV" && which perl`" | ||
| + | </syntaxhighlight> | ||
| − | + | =====Main project module===== | |
| − | + | $PROJECT_MAIN_MODULE must be updated to apply the base-altering trait. Do this in one of two ways: | |
| − | + | ======Change automatically====== | |
| + | |||
| + | If the format of the generated module hasn't changed much, you can just run this patch (which is based on <code>diff -U1</code>): | ||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
| − | + | patch "$PROJECT_MAIN_MODULE" <<'EOF' | |
| − | + | @@ -24,2 +24,4 @@ | |
| + | |||
| + | +use CatalystX::RoleApplicator; | ||
| + | + | ||
| + | extends 'Catalyst'; | ||
| + | @@ -44,2 +46,7 @@ | ||
| + | |||
| + | +# Apply additional roles to the request class | ||
| + | +__PACKAGE__->apply_request_class_roles(qw/ | ||
| + | + Catalyst::TraitFor::Request::ProxyBase | ||
| + | +/); | ||
| + | + | ||
| + | # Start the application | ||
| + | EOF | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | ======Change manually====== | ||
| + | |||
| + | If you can't run the patch as above, you can still simply edit $PROJECT_MAIN_MODULE, making these additions: | ||
| + | |||
| + | <syntaxhighlight lang=perl> | ||
| + | # Insert before the line: extends 'Catalyst'; | ||
| + | |||
| + | use CatalystX::RoleApplicator; | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | <syntaxhighlight lang=perl> | ||
| + | # Insert before the line: __PACKAGE__->setup(); | ||
| − | # | + | # Apply additional roles to the request class |
| − | + | __PACKAGE__->apply_request_class_roles(qw/ | |
| + | Catalyst::TraitFor::Request::ProxyBase | ||
| + | /); | ||
| + | </syntaxhighlight> | ||
| − | + | =====Set the perl path to be used by the scripts===== | |
| − | |||
| − | + | If applicable, update the scripts in the project to use the perlbrew perl instead of what env says: | |
| − | |||
| − | + | <syntaxhighlight lang=bash> | |
| − | + | find "$PROJECT_ROOT" -type f -exec perl -p -i -e "s!/usr/bin/env perl!$MYPERL!g" {} \; | |
| + | </syntaxhighlight> | ||
| − | + | =====Set up document root===== | |
| − | |||
| − | # | + | <syntaxhighlight lang=bash> |
| − | cat >"$ | + | ( |
| + | # Set conservative permissions | ||
| + | umask 0077 | ||
| + | |||
| + | # dispatch.fcgi | ||
| + | cat >"$DOCUMENT_ROOT/dispatch.fcgi" <<EOF | ||
#!$DASH | #!$DASH | ||
"$PROJECT_FASTCGI_SCRIPT" "\$@" | "$PROJECT_FASTCGI_SCRIPT" "\$@" | ||
EOF | EOF | ||
| − | |||
| − | |||
| − | # | + | # .htaccess |
| − | cat >.htaccess <<EOF | + | cat >"$DOCUMENT_ROOT/.htaccess" <<EOF |
| − | RewriteEngine | + | |
| + | RewriteEngine on | ||
| + | |||
| + | # Set X-Request-Base to the URI root found in SCRIPT_URI. | ||
| + | SetEnvIf SCRIPT_URI ^([^/]+//[^/]+) fixed_request_base=$1/ | ||
| + | RequestHeader set X-Request-Base %{fixed_request_base}e env=fixed_request_base | ||
| + | |||
RewriteCond %{ENV:REDIRECT_STATUS} ^$ | RewriteCond %{ENV:REDIRECT_STATUS} ^$ | ||
| − | RewriteRule ^(.*)$ | + | RewriteRule ^(.*)$ dispatch.fcgi/$1 |
| + | |||
EOF | EOF | ||
| + | |||
| + | # Set actual permissions | ||
| + | chmod 755 "$DOCUMENT_ROOT/dispatch.fcgi" | ||
| + | chmod 644 "$DOCUMENT_ROOT/.htaccess" | ||
| + | ) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
Revision as of 10:58, 16 January 2015
Notes on Catalyst, an MVC web framework for perl.
Installation
Other people's instructions
On Dreamhost with perlbrew
Here, I am using perlbrew instead of the typical instructions, and hope to bypass the whole local::lib thing.
Presume that myperl is a perlbrew environment that's already been set up and that its executable is at
/home/someuser/perl5/perlbrew/perls/myperl/bin/perl
Install modules with cpanm:
perlbrew use myperl
cpanm Catalyst::Runtime Catalyst::Devel Catalyst::TraitFor::Request::ProxyBase
Version check
Run the following, which always fails:
perl -M"Catalyst 999"
If the failure is about a version number, the install worked (and the error displays the version number). Otherwise, there was a problem.
Link catalyst.pl
Instructions and tutorials refer to the bootstrap script catalyst.pl. This is installed in the bin dir of the perlbrew environment:
/home/someuser/perl5/perlbrew/perls/myperl/bin/catalyst.pl
To make this less of a mouthful, make this accessible from your path. In this example, I'll qualify it with the name of the perlbrew env in case I want to set this up for multiple sites; anytime the doc says "catalyst.pl" I'll substitute "myperl-catalyst.pl".
ln -s /home/someuser/perl5/perlbrew/perls/myperl/bin/catalyst.pl ~/bin/myperl-catalyst.pl
Test on a site
Here, sub.example.com is a domain that has been set up with FastCGI enabled.
Save the following script, modify the variables SITENAME, CATALYST, PERLENV, and PARENT as necessary, and run. This script will:
- Go to the root specified by $PARENT
- Create a new, empty site named $SITENAME at $PARENT/$SITENAME
- Create and chmod $PARENT/$SITENAME/script/dispatch.fcgi to automatically run the generated FastCGI script
- The reason for this naming is discussed in the Dreamhost wiki.
- This part is skipped if catalyst.pl has not generated the expected *_fastcgi.pl file.
- Replace all instances of "/usr/bin/env perl" with the path of the specified perlbrew perl
- Run perl Makefile.PL, as suggested by catalyst.pl to "make sure your install is complete"
#!/bin/bash
# Load perlbrew env
source ~/perl5/perlbrew/etc/bashrc
SITENAME=Foo
CATALYST=catalyst.pl
PERLENV=myperl
PARENT=~/sub.example.com
myperl="`perlbrew use "$PERLENV" && which perl`"
perlbrew use "$PERLENV" &&
cd "$PARENT" &&
"$CATALYST" "$SITENAME" &&
cd "$SITENAME" &&
(
cd script &&
for fcs in *_fastcgi.pl; do
cat > dispatch.fcgi <<EOF &&
#!/usr/bin/env perl
do '$fcs';
EOF
chmod 755 dispatch.fcgi
done
) &&
# This part corrects all the "/usr/bin/env perl" shebangs with the perlbrew perl
find -type f -exec perl -p -i -e "s!/usr/bin/env perl!$myperl!g" {} \; &&
# "make sure your install is complete"
perl Makefile.PL
After this, visiting the page
http://sub.example.com/Foo/script/dispatch.fcgi/
(note the trailing slash) results in a default welcome screen. (If the result is a 500, something wasn't set up correctly.)
With the following methodology, it is possible to:
- Store the project separately from the document root, preventing access to material in the event of a misconfiguration.
- Prevent, with caveats, the dispatch script from being requested directly by a client.
Pre-flight
- Ensure FastCGI is enabled on the domain.
- Ensure that
dash, or some other minimalist/low-overhead shell, is installed.- We will use a wrapper script rather than a symlink to run the project dispatch script. This way, the script is able to locate itself correctly.
- Ensure the CPAN module
Catalyst::TraitFor::Request::ProxyBaseis installed.- This module is used here to alter the base URI so that requests to the dispatch script cannot be made directly by the client.
Locations
These variables are assumed set:
# The full path to dash (or your choice of minimal sh)
export DASH="$HOME/bin/dash"
# The name of the perlbrew env to use
export MYPERLENV=myperl
# The full path to the domain document root
export DOCUMENT_ROOT="$HOME/sub.example.com"
# The name of the Catalyst project
export PROJECT_NAME=Foo
# The root dir of the Catalyst project
export PROJECT_ROOT="$HOME/catalyst-projects/$PROJECT_NAME"
# The full path to main perl module for the Catalyst project
export PROJECT_MAIN_MODULE="$PROJECT_ROOT/lib/$PROJECT_NAME.pm"
# The full path to the FastCGI script for the Catalyst project
export PROJECT_FASTCGI_SCRIPT="`find "$PROJECT_ROOT/script/" -name '*_fastcgi.pl'`"
# The full path to the perl that should be used
export MYPERL="`perlbrew use "$MYPERLENV" && which perl`"
Main project module
$PROJECT_MAIN_MODULE must be updated to apply the base-altering trait. Do this in one of two ways:
Change automatically
If the format of the generated module hasn't changed much, you can just run this patch (which is based on diff -U1):
patch "$PROJECT_MAIN_MODULE" <<'EOF'
@@ -24,2 +24,4 @@
+use CatalystX::RoleApplicator;
+
extends 'Catalyst';
@@ -44,2 +46,7 @@
+# Apply additional roles to the request class
+__PACKAGE__->apply_request_class_roles(qw/
+ Catalyst::TraitFor::Request::ProxyBase
+/);
+
# Start the application
EOF
Change manually
If you can't run the patch as above, you can still simply edit $PROJECT_MAIN_MODULE, making these additions:
# Insert before the line: extends 'Catalyst';
use CatalystX::RoleApplicator;
# Insert before the line: __PACKAGE__->setup();
# Apply additional roles to the request class
__PACKAGE__->apply_request_class_roles(qw/
Catalyst::TraitFor::Request::ProxyBase
/);
Set the perl path to be used by the scripts
If applicable, update the scripts in the project to use the perlbrew perl instead of what env says:
find "$PROJECT_ROOT" -type f -exec perl -p -i -e "s!/usr/bin/env perl!$MYPERL!g" {} \;
Set up document root
(
# Set conservative permissions
umask 0077
# dispatch.fcgi
cat >"$DOCUMENT_ROOT/dispatch.fcgi" <<EOF
#!$DASH
"$PROJECT_FASTCGI_SCRIPT" "\$@"
EOF
# .htaccess
cat >"$DOCUMENT_ROOT/.htaccess" <<EOF
RewriteEngine on
# Set X-Request-Base to the URI root found in SCRIPT_URI.
SetEnvIf SCRIPT_URI ^([^/]+//[^/]+) fixed_request_base=$1/
RequestHeader set X-Request-Base %{fixed_request_base}e env=fixed_request_base
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(.*)$ dispatch.fcgi/$1
EOF
# Set actual permissions
chmod 755 "$DOCUMENT_ROOT/dispatch.fcgi"
chmod 644 "$DOCUMENT_ROOT/.htaccess"
)