# NAME
Prancer
# SYNOPSIS
When using as part of a web application:
===> foobar.yml
session:
state:
driver: Prancer::Session::State::Cookie
options:
session_key: PSESSION
store:
driver: Prancer::Session::Store::Storable
options:
dir: /tmp/prancer/sessions
static:
path: /static
dir: /srv/www/resources
===> myapp.psgi
#!/usr/bin/env perl
use strict;
use warnings;
use Plack::Runner;
# this just returns a PSGI application. $x can be wrapped with additional
# middleware before sending it along to Plack::Runner.
my $x = MyApp->new("/path/to/foobar.yml")->to_psgi_app();
# run the psgi app through Plack and send it everything from @ARGV. this
# way Plack::Runner will get options like what listening port to use and
# application server to use -- Starman, Twiggy, etc.
my $runner = Plack::Runner->new();
$runner->parse_options(@ARGV);
$runner->run($x);
===> MyApp.pm
package MyApp;
use strict;
use warnings;
use Prancer qw(config);
sub initialize {
my $self = shift;
# in here we can initialize things like plugins
# but this method is not required to be implemented
return;
}
sub handler {
my ($self, $env, $request, $response, $session) = @_;
sub (GET + /) {
$response->header("Content-Type" => "text/plain");
$response->body("Hello, world!");
return $response->finalize(200);
}, sub (GET + /foo) {
$response->header("Content-Type" => "text/plain");
$response->body(sub {
my $writer = shift;
$writer->write("Hello, world!");
$writer->close();
return;
});
}
}
1;
If you save the above snippet as `myapp.psgi` and run it like this:
plackup myapp.psgi
You will get "Hello, world!" in your browser. Or you can use Prancer as part of
a standalone command line application:
#!/usr/bin/env perl
use strict;
use warnings;
use Prancer::Core qw(config);
# the advantage to using Prancer in a standalone application is the ability
# to use a standard configuration and to load plugins for things like
# loggers and database connectors and template engines.
my $x = Prancer::Core->new("/path/to/foobar.yml");
print "Hello, world!;
# DESCRIPTION
Prancer is yet another PSGI framework that provides routing and session
management as well as plugins for logging, database access, and template
engines. It does this by wrapping
[Web::Simple](
https://metacpan.org/pod/Web::Simple) to handle routing and by
wrapping other libraries to bring easy access to things that need to be done in
web applications.
There are two parts to using Prancer for a web application: a package to
contain your application and a script to call your application. Both are
necessary.
The package containing your application should contain a line like this:
use Prancer;
This modifies your application package such that it inherits from Prancer. It
also means that your package must implement the `handler` method and
optionally implement the `initialize` method. As Prancer inherits from
Web::Simple it will also automatically enable the `strict` and `warnings`
pragmas.
As mentioned, putting `use Prancer;` at the top of your package will require
you to implement the `handler` method, like this:
sub handler {
my ($self, $env, $request, $response, $session) = @_;
# routing goes in here.
# see Web::Simple for documentation on writing routing rules.
sub (GET + /) {
$response->header("Content-Type" => "text/plain");
$response->body("Hello, world!");
return $response->finalize(200);
}
}
The `$request` variable is a
[Prancer::Request](
https://metacpan.org/pod/Prancer::Request) object. The
`$response` variable is a
[Prancer::Response](
https://metacpan.org/pod/Prancer::Response) object. The
`$session` variable is a
[Prancer::Session](
https://metacpan.org/pod/Prancer::Session) object. If there
is no configuration for sessions in any of your configuration files then
`$session` will be `undef`.
You may implement your own `new` method in your application but you **MUST**
call `$class->SUPER::new(@_);` to get the configuration file loaded and
any methods exported. As an alternative to implemeting `new` and remembering
to call `SUPER::new`, Prancer will make a call to `->initialize` at the
end of its own implementation of `new` so things that you might put in `new`
can instead be put into `initialize`, like this:
sub initialize {
my $self = shift;
# this is where you can initialize things when your package is created
return;
}
By default, Prancer does not export anything into your package's namespace.
However, that doesn't mean that there is not anything that it _could_ export
were one to ask:
use Prancer qw(config);
Importing `config` will make the keyword `config` available which gives
access to any configuration options loaded by Prancer.
The second part of the Prancer equation is the script that creates and calls
your package. This can be a pretty small and standard little script, like this:
my $myapp = MyApp->new("/path/to/foobar.yml")
my $psgi = $myapp->to_psgi_app();
`$myapp` is just an instance of your package. You can pass to `new` either
one specific configuration file or a directory containing lots of configuration
files. The functionality is documented in `Prancer::Config`.
`$psgi` is just a PSGI app that you can send to
[Plack::Runner](
https://metacpan.org/pod/Plack::Runner) or whatever you use to
run PSGI apps. You can also wrap middleware around `$app`.
my $psgi = $myapp->to_psgi_app();
$psgi = Plack::Middleware::Runtime->wrap($psgi);
# CONFIGURATION
Prancer needs a configuration file. Ok, it doesn't _need_ a configuration file
file. By default, Prancer does not require any configuration. But it is less
useful without one. You _could_ always create your application like this:
my $app = MyApp->new->to_psgi_app();
How Prancer loads configuration files is documented in
[Prancer::Config](
https://metacpan.org/pod/Prancer::Config). Anything you put
into your configuration file is available to your application.
There are two special configuration keys reserved by Prancer. The key
`session` will configure Prancer's session as documented in
[Prancer::Session](
https://metacpan.org/pod/Prancer::Session). The key `static`
will configure static file loading through
[Plack::Middleware::Static](
https://metacpan.org/pod/Plack::Middleware::Static).
To configure static file loading you can add this to your configuration file:
static:
path: /static
dir: /path/to/my/resources
The `dir` option is required to indicate the root directory for your static
resources. The `path` option indicates the web path to link to your static
resources. If no path is not provided then static files can be accessed under
`/static` by default.
# CREDITS
This module could have been written except on the shoulders of the following
giants:
- The name "Prancer" is a riff on the popular PSGI framework [Dancer](
https://metacpan.org/pod/Dancer) and [Dancer2](
https://metacpan.org/pod/Dancer2). [Prancer::Config](
https://metacpan.org/pod/Prancer::Config) is derived directly from [Dancer2::Core::Role::Config](
https://metacpan.org/pod/Dancer2::Core::Role::Config). Thank you to the Dancer/Dancer2 teams.
- [Prancer::Database](
https://metacpan.org/pod/Prancer::Database) is derived from [Dancer::Plugin::Database](
https://metacpan.org/pod/Dancer::Plugin::Database). Thank you to David Precious.
- [Prancer::Request](
https://metacpan.org/pod/Prancer::Request), [Prancer::Request::Upload](
https://metacpan.org/pod/Prancer::Request::Upload), [Prancer::Response](
https://metacpan.org/pod/Prancer::Response), [Prancer::Session](
https://metacpan.org/pod/Prancer::Session) and the session packages are but thin wrappers with minor modifications to [Plack::Request](
https://metacpan.org/pod/Plack::Request), [Plack::Request::Upload](
https://metacpan.org/pod/Plack::Request::Upload), [Plack::Response](
https://metacpan.org/pod/Plack::Response), and [Plack::Middleware::Session](
https://metacpan.org/pod/Plack::Middleware::Session). Thank you to Tatsuhiko Miyagawa.
- The entire routing functionality of this module is offloaded to [Web::Simple](
https://metacpan.org/pod/Web::Simple). Thank you to Matt Trout for some great code that I am able to easily leverage.
# COPYRIGHT
Copyright 2013, 2014 Paul Lockaby. All rights reserved.
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.
# SEE ALSO
- [Plack](
https://metacpan.org/pod/Plack)
- [Web::Simple](
https://metacpan.org/pod/Web::Simple)