From: Andy Grundman Date: Thu, 23 Jun 2005 21:31:52 +0000 (+0000) Subject: Importing C::P::RequireSSL 0.01 X-Git-Tag: v0.01^0 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Plugin-RequireSSL.git;a=commitdiff_plain;h=1763fe29e75464780d6930c4b49396b6722b629a Importing C::P::RequireSSL 0.01 --- diff --git a/Build.PL b/Build.PL new file mode 100644 index 0000000..58148c9 --- /dev/null +++ b/Build.PL @@ -0,0 +1,14 @@ +use strict; +use Module::Build; + +my $build = Module::Build->new( + create_makefile_pl => 'passthrough', + license => 'perl', + module_name => 'Catalyst::Plugin::RequireSSL', + requires => { 'Catalyst' => '5.23' }, + create_makefile_pl => 'passthrough', + test_files => [ + glob('t/*.t') + ] +); +$build->create_build_script; diff --git a/Changes b/Changes new file mode 100644 index 0000000..a76039c --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for Perl extension Catalyst::Plugin::RequireSSL + +0.01 2005-06-08 23:45:00 + - initial release diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..731a9a7 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,10 @@ +Build.PL +Changes +lib/Catalyst/Plugin/RequireSSL.pm +Makefile.PL +MANIFEST This list of files +META.yml +README +t/01use.t +t/02pod.t +t/03podcoverage.t diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..b7a20d3 --- /dev/null +++ b/META.yml @@ -0,0 +1,8 @@ +--- #YAML:1.0 +name: Catalyst-Plugin-RequireSSL +version: 0.01 +author: + - Andy Grundman, C +abstract: Force SSL mode on select pages +license: perl +generated_by: Module::Build version 0.2604, without YAML.pm diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..51d31fd --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,31 @@ +# Note: this file was auto-generated by Module::Build::Compat version 0.03 + + unless (eval "use Module::Build::Compat 0.02; 1" ) { + print "This module requires Module::Build to install itself.\n"; + + require ExtUtils::MakeMaker; + my $yn = ExtUtils::MakeMaker::prompt + (' Install Module::Build now from CPAN?', 'y'); + + unless ($yn =~ /^y/i) { + die " *** Cannot install without Module::Build. Exiting ...\n"; + } + + require Cwd; + require File::Spec; + require CPAN; + + # Save this 'cause CPAN will chdir all over the place. + my $cwd = Cwd::cwd(); + my $makefile = File::Spec->rel2abs($0); + + CPAN::Shell->install('Module::Build::Compat') + or die " *** Cannot install without Module::Build. Exiting ...\n"; + + chdir $cwd or die "Cannot chdir() back to $cwd: $!"; + } + eval "use Module::Build::Compat 0.02; 1" or die $@; + use lib '_build/lib'; + Module::Build::Compat->run_build_pl(args => \@ARGV); + require Module::Build; + Module::Build::Compat->write_makefile(build_class => 'Module::Build'); diff --git a/README b/README new file mode 100644 index 0000000..c9bc78b --- /dev/null +++ b/README @@ -0,0 +1,137 @@ +NAME + Catalyst::Plugin::PageCache - Cache the output of entire pages + +SYNOPSIS + use Catalyst 'PageCache'; + + MyApp->config->{page_cache} = { + expires => 300, + set_http_headers => 1, + auto_cache => [ + '/view/.*', + '/list', + ], + debug => 1, + }; + + $c->cache_page( '3600' ); + + $c->clear_cached_page( '/list' ); + +DESCRIPTION + Many dynamic websites perform heavy processing on most pages, yet this + information may rarely change from request to request. Using the + PageCache plugin, you can cache the full output of different pages so + they are served to your visitors as fast as possible. This method of + caching is very useful for withstanding a Slashdotting, for example. + + This plugin requires that you also load a Cache plugin. Please see the + Known Issues when choosing a cache backend. + +WARNINGS + PageCache should be placed at the end of your plugin list. + + You should only use the page cache on pages which have NO user-specific + or customized content. Also, be careful if caching a page which may + forward to another controller. For example, if you cache a page behind a + login screen, the logged-in version may be cached and served to + unauthenticated users. + + Note that pages that result from POST requests will never be cached. + +PERFORMANCE + On my Athlon XP 1800+ Linux server, a cached page is served in 0.008 + seconds when using the HTTP::Daemon server and any of the Cache plugins. + +CONFIGURATION + Configuration is optional. You may define the following configuration + values: + + expires => $seconds + + This will set the default expiration time for all page caches. If you do + not specify this, expiration defaults to 300 seconds (5 minutes). + + set_http_headers => 1 + + Enabling this value will cause Catalyst to set the correct HTTP headers + to allow browsers and proxy servers to cache your page. This will + further reduce the load on your server. The headers are set in such a + way that the browser/proxy cache will expire at the same time as your + cache. The Last-Modified header will be preserved if you have already + specified it. + + auto_cache => [ + $uri, + ] + + To automatically cache certain pages, or all pages, you can specify + auto-cache URIs as an array reference. Any controller within your + application that matches one of the auto_cache URIs will be cached using + the default expiration time. URIs may be specified as absolute: '/list' + or as a regex: '/view/.*' + + debug => 1 + + This will print additional debugging information to the Catalyst log. + You will need to have -Debug enabled to see these messages. + + METHODS + cache_page + Call cache_page in any controller method you wish to be cached. + + $c->cache_page( $expire ); + + The page will be cached for $expire seconds. Every user who visits + the URI(s) referenced by that controller will receive the page + directly from cache. Your controller will not be processed again + until the cache expires. You can set this value to as low as 60 + seconds if you have heavy traffic to greatly improve site + performance. + + clear_cached_page + To clear the cached value for a URI, you may call clear_cached_page. + + $c->clear_cached_page( '/view/userlist' ); + $c->clear_cached_page( '/view/.*' ); + + This method takes an absolute path or regular expression. For + obvious reasons, this must be called from a different controller + than the cached controller. You may for example wish to build an + admin page that lets you clear page caches. + + dispatch (extended) + Bypass the dispatch phase and send cached content if available + + finalize (extended) + Cache the page output if requested. + + setup + Setup default values. + + _page_cache_key + Returns a cache key for the current page. + +KNOWN ISSUES + It is not currently possible to cache pages served from the Static + plugin. If you're concerned enough about performance to use this plugin, + you should be serving static files directly from your web server anyway. + + Cache::FastMmap does not have the ability to specify different + expiration times for cached data. Therefore, if your + MyApp->config->{cache}->{expires} value is set to anything other than 0, + you may experience problems with the clear_cached_page method, because + the cache index may be removed. For best results, you may wish to use + Cache::FileCache or Cache::Memcached as your cache backend. + +SEE ALSO + Catalyst, Catalyst::Plugin::Cache::FastMmap, + Catalyst::Plugin::Cache::FileCache, Catalyst::Plugin::Cache::Memcached + +AUTHOR + Andy Grundman, "andy@hybridized.org" + +COPYRIGHT + This program is free software, you can redistribute it and/or modify it + under the same terms as Perl itself. + diff --git a/lib/Catalyst/Plugin/RequireSSL.pm b/lib/Catalyst/Plugin/RequireSSL.pm new file mode 100644 index 0000000..590fd31 --- /dev/null +++ b/lib/Catalyst/Plugin/RequireSSL.pm @@ -0,0 +1,195 @@ +package Catalyst::Plugin::RequireSSL; + +use strict; +use base qw/Class::Accessor::Fast/; +use NEXT; + +our $VERSION = '0.01'; + +__PACKAGE__->mk_accessors( '_require_ssl' ); + +=head1 NAME + +Catalyst::Plugin::RequireSSL - Force SSL mode on select pages + +=head1 SYNOPSIS + + use Catalyst 'RequireSSL'; + + MyApp->config->{require_ssl} = { + https => 'secure.mydomain.com', + http => 'www.mydomain.com', + remain_in_ssl => 0, + }; + + $c->require_ssl; + +=head1 DESCRIPTION + +Use this plugin if you wish to selectively force SSL mode on some of your web pages, +for example a user login form or shopping cart. + +Simply place $c->require_ssl calls in any controller method you wish to be secured. + +This plugin will automatically disable itself if you are running under the standalone +HTTP::Daemon Catalyst server. A warning message will be printed to the log file whenever +an SSL redirect would have occurred. + +=head1 WARNINGS + +If you utilize different servers or hostnames for non-SSL and SSL requests, and you rely +on a session cookie to determine redirection (i.e for a login page), your cookie must +be visible to both servers. For more information, see the documentation for the Session plugin +you are using. + +=head1 CONFIGURATION + +Configuration is optional. You may define the following configuration values: + + https => $ssl_host + +If your SSL domain name is different from your non-SSL domain, set this value. + + http => $non_ssl_host + +If you have set the https value above, you must also set the hostname of your non-SSL +server. + + remain_in_ssl + +If you'd like your users to remain in SSL mode after visiting an SSL-required page, you can +set this option to 1. By default, users will be redirected back to non-SSL mode as soon as +possible. + +=head2 METHODS + +=over 4 + +=item require_ssl + +Call require_ssl in any controller method you wish to be secured. + + $c->require_ssl; + +The browser will be redirected to the same path on your SSL server. POST requests +are never redirected. + +=cut + +sub require_ssl { + my $c = shift; + + $c->_require_ssl( 1 ); + + unless ( $c->req->secure || $c->req->method eq "POST" ) { + if ( $c->config->{require_ssl}->{disabled} ) { + $c->log->warn( "RequireSSL: Would have redirected to " . $c->_redirect_uri( 'https' ) ); + } else { + $c->res->redirect( $c->_redirect_uri( 'https' ) ); + } + } +} + +=item finalize (extended) + +Redirect back to non-SSL mode if necessary. + +=cut + +sub finalize { + my $c = shift; + + # redirect unless: + # we're not in SSL mode, + # it's a POST request, + # we're already required to be in SSL for this request, + # or the user doesn't want us to redirect + unless ( !$c->req->secure + || $c->req->method eq "POST" + || $c->_require_ssl + || $c->config->{require_ssl}->{remain_in_ssl} ) { + $c->res->redirect( $c->_redirect_uri( 'http' ) ); + } + + return $c->NEXT::finalize(@_); +} + +=item setup + +Setup default values. + +=cut + +sub setup { + my $c = shift; + + $c->NEXT::setup(@_); + + # disable the plugin when running under certain engines which don't support SSL + # XXX: I didn't include Catalyst::Engine::Server here as it may be used as a backend + # in a proxy setup. + if ( $c->engine eq "Catalyst::Engine::HTTP" ) { + $c->config->{require_ssl}->{disabled} = 1; + $c->log->warn( "RequireSSL: Disabling SSL redirection while running under " . $c->engine ); + } +} + +=item _redirect_uri + +Generate the redirection URI. + +=cut + +sub _redirect_uri { + my ( $c, $type ) = @_; + + # XXX: Cat needs a $c->req->host method... + # until then, strip off the leading protocol from base + unless ( $c->config->{require_ssl}->{$type} ) { + my $host = $c->req->base; + $host =~ s/^http(s?):\/\///; + $c->config->{require_ssl}->{$type} = $host; + } + + $c->config->{require_ssl}->{$type} .= '/' + unless ( $c->config->{require_ssl}->{$type} =~ /\/$/ ); + + my $redir = $type . '://' . $c->config->{require_ssl}->{$type} . $c->req->path; + if ( scalar keys %{ $c->req->params } ) { + my @params = (); + foreach my $k ( sort keys %{ $c->req->params } ) { + push @params, $k . "=" . $c->req->params->{$k}; + } + $redir .= "?" . join "&", @params; + } + + return $redir; +} + +=back + +=head1 KNOWN ISSUES + +When viewing an SSL-required page that uses static files served from the Static plugin, the static +files are redirected to the non-SSL path. It may be possible to work around this by checking the +referer protocol, but currently there is no way to determine if a file being served is static content. + +For best results, always serve static files directly from your web server without using the Static +plugin. + +=head1 SEE ALSO + +L + +=head1 AUTHOR + +Andy Grundman, C + +=head1 COPYRIGHT + +This program is free software, you can redistribute it and/or modify it under +the same terms as Perl itself. + +=cut + +1; diff --git a/t/01use.t b/t/01use.t new file mode 100644 index 0000000..b47fbda --- /dev/null +++ b/t/01use.t @@ -0,0 +1,3 @@ +use Test::More tests => 1; + +use_ok('Catalyst::Plugin::RequireSSL'); diff --git a/t/02pod.t b/t/02pod.t new file mode 100644 index 0000000..1647794 --- /dev/null +++ b/t/02pod.t @@ -0,0 +1,7 @@ +use Test::More; + +eval "use Test::Pod 1.14"; +plan skip_all => 'Test::Pod 1.14 required' if $@; +plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD}; + +all_pod_files_ok(); diff --git a/t/03podcoverage.t b/t/03podcoverage.t new file mode 100644 index 0000000..d91be5e --- /dev/null +++ b/t/03podcoverage.t @@ -0,0 +1,7 @@ +use Test::More; + +eval "use Test::Pod::Coverage 1.04"; +plan skip_all => 'Test::Pod::Coverage 1.04 required' if $@; +plan skip_all => 'set TEST_POD to enable this test' unless $ENV{TEST_POD}; + +all_pod_coverage_ok();