Squatting
view release on metacpan or search on metacpan
lib/Squatting.pm view on Meta::CPAN
: "$_=".uri_escape($input->{$_})
} keys %$input);
}
$path;
};
# ($controller, \@regex_captures) = D($path) # Return controller and captures for a path
*{$p."::D"} = sub {
my $url = uri_unescape($_[0]);
my $C = \@{$p.'::Controllers::C'};
my ($c, @regex_captures);
for $c (@$C) {
for (@{$c->urls}) {
if (@regex_captures = ($url =~ qr{^$_$})) {
pop @regex_captures if ($#+ == 0);
return ($c, \@regex_captures);
}
}
}
($Squatting::Controller::r404, []);
};
*{$p."::Controllers::C"} = sub {
Squatting::Controller->new(@_, app => $p)
};
*{$p."::Views::V"} = sub {
Squatting::View->new(@_)
};
}
# Squatting plugins may be anywhere in Squatting::*::* but by convention
# (and for fun) you should use poetic diction in your package names.
#
# Squatting::On::Continuity
# Squatting::On::Catalyst
# Squatting::On::CGI
# Squatting::On::Jifty
#
# (ALL YOUR FRAMEWORK ARE BELONG TO US)
#
# Squatting::With::Impunity (What could we do w/ this name?)
# Squatting::With::Log4Perl (which is how we could add logging support)
#
# (etc)
sub component_base_class { __PACKAGE__ }
# 1
# App->mount($AnotherApp, $prefix) # Map another app on to a URL $prefix.
sub mount {
my ($app, $other, $prefix) = @_;
push @{$app."::O"}, $other;
push @{$app."::Controllers::C"}, map {
my $urls = $_->urls;
$_->urls = [ map { $prefix.$_ } @$urls ];
$_;
} @{$other."::Controllers::C"}
}
# 2
# App->relocate($prefix) # Map main app to a URL $prefix
sub relocate {
my ($app, $prefix) = @_;
for (@{$app."::Controllers::C"}) {
my $urls = $_->urls;
$_->urls = [ map { $prefix.$_ } @$urls ];
}
${$app."::CONFIG"}{relocated} = $prefix;
}
# 3
# App->init # Initialize $app
sub init {
$_->init for (@{$_[0]."::O"});
%{$_[0]."::Controllers::C"} = map { $_->name => $_ } @{$_[0]."::Controllers::C"};
%{$_[0]."::Views::V"} = map { $_->name => $_ } @{$_[0]."::Views::V"};
}
# App->service($controller, @args) # Handle an HTTP request
sub service {
my ($app, $c, @args) = grep { defined } @_;
my $method = lc $c->env->{REQUEST_METHOD};
my $content;
eval { $content = $c->$method(@args) };
die $@ if (ref($@) =~ /^HTTP::Exception/); # Pass HTTP::Exceptions on up
warn "EXCEPTION: $@" if ($@);
my $cookies = $c->cookies;
$c->headers->{'Set-Cookie'} = join("; ",
map { CGI::Cookie->new( -name => $_, %{$cookies->{$_}} ) }
grep { ref $cookies->{$_} eq 'HASH' }
keys %$cookies) if (%$cookies);
$content;
}
1;
=head1 NAME
Squatting - A Camping-inspired Web Microframework for Perl
=head1 SYNOPSIS
Running an App:
$ squatting App
Please contact me at: http://localhost:4234/
Check out our ASCII art logo:
$ squatting --logo
What a basic App looks like:
# STEP 1 => Use Squatting for your App
{
package App; # <-- I hope it's obvious that this name can whatever you want.
use Squatting;
our %CONFIG; # <-- standard app config goes here
}
# STEP 2 => Define the App's Controllers
{
package App::Controllers;
# Setup a list of controller objects in @C using the C() function.
lib/Squatting.pm view on Meta::CPAN
=back
B<*> RESTless controllers currently only work when you're L<Squatting::On::Continuity>.
=head1 API
=head2 Use as a Base Class for Squatting Applications
package App;
use Squatting;
our %CONFIG = ();
1;
Just C<use>ing Squatting makes a lot of magic happen. In the example above:
=over 4
=item App becomes a subclass of Squatting.
=item App::Controllers is given this app's R() and C() functions.
=item App::Views is given this app's R() and V() functions.
=back
=head3 App->service($controller, @args)
Every time an HTTP request comes in, this method is called with a controller
object and a list of arguments. The controller will then be invoked with the
HTTP method that was requested (like GET or POST), and it will return the
content of the response as a string.
B<NOTE>: If you want to do anything before, after, or around an HTTP request,
this is the method you should override in your subclass.
=head3 App->init
This method takes no parameters and initializes some internal variables.
B<NOTE>: You can override this method if you want to do more things when
the App is initialized.
=head3 App->mount($AnotherApp => $prefix)
XXX - The C<mount()> has been moved out of the core and into
L<Squatting::With::Mount>. Furthermore, Squatting::With::Mount has
been implemented using L<Squatting::On::Squatting>.
This method will mount another Squatting app at the specified prefix.
App->mount('My::Blog' => '/my/ridiculous/rantings');
App->mount('Forum' => '/forum');
App->mount('ChatterBox' => '/chat');
B<NOTE>: You can only mount an app once. Don't try to mount it again
at some other prefix, because it won't work. This is a consequence
of storing so much information in package variables and a strong argument
for going all objects all the time.
=head3 App->relocate($prefix)
This method will relocate a Squatting app to the specified prefix. It's useful
for embedding a Squatting app into apps written in other frameworks.
This also has a side-effect of setting C<$CONFIG{relocated}> to C<$prefix>.
=head2 Use as a Helper for Controllers
In this package, you will define a list of L<Squatting::Controller> objects in C<@C>.
package App::Controllers;
use Squatting ':controllers';
our @C = (
C(...),
C(...),
C(...),
);
=head3 C($name => \@urls, %methods)
This is a shortcut for:
Squatting::Controller->new(
$name => \@urls,
app => $App,
%methods
);
=head3 R($name, @args, [ \%params ])
R() is a URL generation function that takes a controller name and a list of
arguments. You may also pass in a hashref representing CGI variables as the
very last parameter to this function.
B<Example>: Given the following controllers, R() would respond like this.
# Example Controllers
C(Home => [ '/' ]);
C(Profile => [ '/~(\w+)', '/~(\w+)\.(\w+)' ]);
# Generated URLs
R('Home') # "/"
R('Home', { foo => 1, bar => 2}) # "/?foo=1&bar=2"
R('Profile', 'larry') # "/~larry"
R('Profile', 'larry', 'json') # "/~larry.json"
As you can see, C<@args> represents the regexp captures, and C<\%params>
represents the CGI query parameters.
=head2 Use as a Helper for Views
In this package, you will define a list of L<Squatting::View> objects in C<@V>.
package App::Views;
use Squatting ':views';
our @V = (
V(
'html',
home => sub { "<h1>Home</h1>" },
),
);
=head3 V($name, %methods)
This is a shortcut for:
( run in 0.817 second using v1.01-cache-2.11-cpan-71847e10f99 )