Introducing Modern Perl

download Introducing Modern Perl

If you can't read please download the document

Transcript of Introducing Modern Perl

What is Perl

Introducing
Modern Perl

Dave CrossMagnum Solutions [email protected]

Modern Perl

Perl has been around for a long time

Achieved great popularity in the 1990s

The duct tape of the internet

Perl has moved on a lot since then

Many people's perceptions of Perl haven't

Modern Perl

Keeping up to date with Perl

Surveying modern modules and techniques

A lot to cover

Only an overview

Plenty of pointers to more information

What We Will Cover

Template Toolkit

DateTime

DBIx::Class

TryCatch

What We Will Cover

Moose

autodie

Catalyst

PSGI/Plack

Schedule

09:00 Begin

11:00 Coffee break

13:00 Lunch

14:00 Begin

16:00 Coffee break

17:00 End

Resources

Slides available on-linehttp://mag-sol.com/train/yapc/2010

Also see Slidesharehttp://www.slideshare.net/davorg/slideshows

Get Satisfactionhttp://getsatisfaction.com/magnum

Template Toolkit

Templates

Many people use templates to produce web pages

Advantages are well known

Standard look and feel (static/dynamic)

Reusable components

Separation of code logic from display logic

Different skill-sets (HTML vs Perl)

DIY Templating

Must be easy - so many people do it

See perlfaq4

How can I expand variables in text strings?

DIY Templating

$text =
'this has a $foo in it and a $bar';

%user_defs = (
foo => 23,
bar => 19,
);

$text =~ s/\$(\w+)/$user_defs{$1}/g;

Don't do that

Templating Options

Dozens of template modules on CPAN

Text::Template, HTML::Template, Mason, Template Toolkit

Many, many more

Questions to considerHTML only?

Template language

Template Toolkit

http://tt2.org/

Very powerful

Both web and non-web

Simple template language

Plugins give access to much of CPAN

Can use Perl code if you wantBut don't do that

Good Book Too!

The Template Equation

Data + Template = Output

Data + Alternative Template = Alternative Output

Different views of the same data

Only the template changes

Simple TT Example

use Template;
use My::Object;
my ($id, $format) = @ARGV;
$format ||= 'html';
my $obj = My::Object->new($id)
or die;
my $tt = Template->new;
$tt->process("$format.tt",
{ obj => $obj },
"$id.$format")
or die $tt->error;

html.tt



[% obj.name %]


[% obj.name %]


[% obj.desc %]


  • [% FOREACH child IN obj.children -%]
  • [% child.name %]
    [% END %]

    text.tt

    [% obj.name | upper %]

    Image: [% obj.img %]
    [% obj.desc %]

    [% FOREACH child IN obj.children -%]
    * [% child.name %]
    [% END %]

    Adding New Formats

    No new code required

    Just add new output template

    Perl programmer need not be involved

    Equation Revisited

    Data + Template = OutputTemplate Toolkit

    Template + Output = DataTemplate::Extract

    Data + Output = TemplateTemplate::Generate

    DateTime

    Dates & Times

    Perl has built-in functions to handle dates and times

    time seconds since 1st Jan 1970

    localtime convert to human-readable

    timelocal (in Time::Local) inverse of localtime

    strftime (in POSIX) formatting dates and times

    Dates & Times on CPAN

    Look to CPAN for a better answer

    Dozens of date/time modules on CPAN

    Date::Manip is almost never what you want

    Date::Calc, Date::Parse, Class::Date, Date::Simple, etc

    Which one do you choose?

    Perl DateTime Project

    http://datetime.perl.org/

    "The DateTime family of modules present a unified way to handle dates and times in Perl"

    "unified" is good

    Dozens of modules that work together in a consistent fashion

    Using DateTime

    use DateTime;

    my $dt = DateTime->now;
    say $dt; # 2010-08-02T10:06:07
    say $dt->dmy; # 2010-08-02
    say $dt->hms; # 10:06:07

    Using DateTime

    use DateTime;

    my $dt = DateTime->new(year => 2010,
    month => 8,
    day => 2);

    say $dt->ymd('/'); # 2010/08/02
    say $dt->month; # 8
    say $dt->month_name; # August

    Arithmetic

    A DateTime object is a point in time

    For date arithmetic you need a duration

    Number of years, weeks, days, etc

    Arithmetic

    use DateTime;
    my $dt = DateTime->new(year => 2010,
    month => 8,
    day => 2);

    my $two_weeks =
    DateTime::Duration->new(weeks => 2);
    $dt += $two_weeks;
    say $dt;
    # 2010-08-16T00:00:00

    Formatting Output

    use DateTime;
    my $dt = DateTime->new(year => 2010,
    month => 4,
    day => 14);
    say $dt->strftime('%A, %d %B %Y');
    # Wednesday, 14 April 2010

    strftime uses UNIX standards

    Control input format with DateTime::Format::Strptime

    Parsing & Formatting

    Ready made parsers and formatters for popular date and time formats

    DateTime::Format::HTTP

    DateTime::Format::MySQL

    DateTime::Format::Excel

    DateTime::Format::Babythe big hand is on...

    Alternative Calendars

    Handling non-standard calendars

    DateTime::Calendar::Julian

    DateTime::Calendar::Hebrew

    DateTime::Calendar::Mayan

    DateTime::Fiction::JRRTolkien::Shire

    Calendar Examples

    use DateTime::Calendar::Mayan;

    my $dt = DateTime::Calendar::Mayan->now;

    say $dt->date; # 12.19.17.9.13

    use DateTime::Fiction::JRRTolkien::Shire;

    my $dt =
    DateTime::Fiction::JRRTolkien::Shire->now;

    say $dt->on_date; # Trewsday 14 Afterlithe 7474

    DBIx::Class

    Object Relational Mapping

    Mapping database relations into objects

    Tables (relations) map onto classes

    Rows (tuples) map onto objects

    Columns (attributes) map onto attributes

    Don't write SQL

    SQL Is Tedious

    Select the id and name from this table

    Select all the details of this row

    Select something about related tables

    Update this row with these values

    Insert a new record with these values

    Delete this record

    Replacing SQL

    Instead of

    SELECT *
    FROM my_table
    WHERE my_id = 10

    and then dealing with the prepare/execute/fetch code

    Replacing SQL

    We can write

    use My::Object;

    # warning! not a real orm
    my $obj = My::Object->retrieve(10)

    Or something similar

    Writing An ORM Layer

    Not actually that hard to do yourself

    Each class needs an associated table

    Each class needs a list of columns

    Create simple SQL for basic CRUD operations

    Don't do that

    Perl ORM Options

    Plenty of choices on CPAN

    Class::DBI

    Rose::DB::Object

    ORLite

    DBIx::ClassThe current favourite

    Fey::ORM

    DBIx::Class

    Standing on the shoulders of giants

    Learning from problems in Class::DBI

    More flexible

    More powerful

    DBIx::Class Example

    Modeling a CD collection

    Three tables

    artist (artistid, name)

    cd (cdid, artist, title)

    track (trackid, cd, title)

    Main Schema

    Define main schema class

    Music/DB.pm

    package Music::DB;
    use base qw/DBIx::Class::Schema/;

    __PACKAGE__->load_classes();

    1;

    Object Classes - Artist

    Music/DB/Artist.pm

    package Music::DB::Artist;
    use base qw/DBIx::Class/;
    __PACKAGE__->load_components(qw/Core/);
    __PACKAGE__->table('artist');
    __PACKAGE__->add_columns(qw/ artistid
    name /);
    __PACKAGE__->set_primary_key('artistid');
    __PACKAGE__->has_many(cds =>
    'Music::DB::Cd');
    1;

    Object Classes- CD

    Music/DB/CD.pm

    package Music::DB::CD;
    use base qw/DBIx::Class/;
    __PACKAGE__->load_components(qw/Core/);
    __PACKAGE__->table('cd');
    __PACKAGE__->add_columns(qw/ cdid artist
    title year /);
    __PACKAGE__->set_primary_key('cdid');
    __PACKAGE__->belongs_to(
    artist => 'Music::DB:Artist');
    1;

    Inserting Artists

    my $schema =
    Music::DB->connect($dbi_str);

    my @artists = ('Florence + The Machine',
    'Belle and Sebastian');

    my $art_rs = $schema->resultset('Artist');

    foreach (@artists) {
    $art_rs->create({ name => $_ });
    }

    Inserting CDs

    Hash of Artists and CDs

    my %cds = (
    'Lungs' =>
    'Florence + The Machine',
    'The Boy With The Arab Strap' =>
    'Belle and Sebastian',
    'Dear Catastrophe Waitress' =>
    'Belle and Sebastian',
    );

    Inserting CDs

    Find each artist and insert CD

    foreach (keys $cds) {
    my ($artist) = $art_rs->search(
    { name => $cds{$_} }
    );

    $artist->add_to_cds({
    title => $_,
    });
    }

    Retrieving Data

    Get CDs by artist

    my $name = 'Belle and Sebastian';
    my ($artist) = $art_rs->search({
    name => $name,
    });

    foreach ($artist->cds) {
    say $_->title;
    }

    Searching for Data

    Search conditions can be more complex

    Alternatives

    $rs->search({year => 2006},
    {year => 2007});

    Like$rs->search({name =>
    { 'like', 'Dav%' }});

    Searching for Data

    Combinations

    $rs->search({forename =>
    { 'like', 'Dav%' },
    surname => 'Cross' });

    Don't Repeat Yourself

    There's a problem with this approach

    Information is repeated

    Columns and relationships defined in the database schema

    Columns and relationships defined in class definitions

    Repeated Information

    CREATE TABLE artist (
    artistid INTEGER PRIMARY KEY,
    name TEXT NOT NULL
    );

    Repeated Information

    package Music::DB::Artist;
    use base qw/DBIx::Class/;
    __PACKAGE__->load_components(qw/Core/);
    __PACKAGE__->table('artist');
    __PACKAGE__->add_columns(qw/ artistid
    name /);
    __PACKAGE__->set_primary_key('artistid');
    __PACKAGE__->has_many(cds =>
    'Music::DB::Cd');
    1;

    Database Metadata

    Some people don't put enough metadata in their databases

    Just tables and columns

    No relationships. No constraints

    You may as well make each column VARCHAR(255)

    Database Metadata

    Describe your data in your database

    It's what your database is for

    It's what your database does best

    No Metadata (Excuse 1)

    "This is the only application that will ever access this database"

    Nonsense

    All data will be shared eventually

    People will update your database using other applications

    Can you guarantee that someone won't use mysql to update your database?

    No Metadata (Excuse 2)

    "Database doesn't support those features"

    Nonsense

    MySQL 3.x is not a databaseIt's a set of data files with a vaguely SQL-like query syntax

    MySQL 4.x is a lot better

    MySQL 5.x is most of the way there

    Don't be constrained by using inferior tools

    DBIC::Schema::Loader

    Creates classes by querying your database metadata

    No more repeated data

    We are now DRY

    Schema definitions in one place

    But...

    Performance problems

    Performance Problems

    You don't really want to generate all your class definitions each time your program is run

    Need to generate the classes in advance

    dump_to_dir method

    Regenerate classes each time schema changes

    Alternative Approach

    Need one canonical definition of the data tables

    Doesn't need to be SQL DDL

    Could be Perl code

    Generate DDL from DBIx::Class definitionsHarder approach

    Might need to generate ALTER TABLE

    Conclusions

    ORM is a bridge between relational objects and program objects

    Avoid writing SQL in common cases

    DBIx::Class is the currently fashionable module

    Caveat: ORM may be overkill for simple programs

    More Information

    Manual pages (on CPAN)

    DBIx::Class

    DBIx::Class::Manual::*

    DBIx::Class::Schema::Loader

    Mailing list (Google for it)

    TryCatch

    Error Handling

    How do you handle errors in your code?

    Return error values from subroutines

    sub get_object {
    my ($class, $id) = @_;
    if (my $obj = find_obj_in_db($id)) {
    return $obj;
    } else {
    return;
    }
    }

    Problems

    What if someone doesn't check return code?

    my $obj = MyClass->get_object(100);
    print $obj->name; # error

    Caller assumes that $obj is a valid object

    Bad things follow

    Basic Exceptions

    Throw an exception instead

    sub get_object {
    my ($class, $id) = @_;
    if (my $obj = find_obj_in_db($id)) {
    return $obj;
    } else {
    die No object found with id: $id;
    }
    }

    Now caller has to deal with exceptions

    Dealing with Exceptions

    Use eval to catch exceptions

    my $obj = eval {
    MyClass->get_object(100)
    };

    if ($@) {
    # handle exception...
    } else {
    print $obj->name; # error
    }

    Exceptions as Objects

    $@ can be set to an object

    sub get_object {
    my ($class, $id) = @_;
    if (my $obj = find_obj_in_db($id)) {
    return $obj;
    } else {
    die MyException->new(
    type => 'obj_not_found',
    id => $id,
    );
    }
    }

    Try Catch

    TryCatch adds syntactic sugar

    try {
    ...
    }
    catch ($e) {
    ...
    }

    Looks a lot like many other languages

    TryCatch with Scalar

    try {
    some_function_that_might_die();
    }
    catch ($e) {
    if ($e =~ /some error/) {
    # handle error
    } else {
    die $e;
    }
    }

    TryCatch with Object

    try {
    some_function_that_might_die();
    }
    catch ($e) {
    if ($e->type eq 'file') {
    # handle error
    } else {
    die $e;
    }
    }

    Better Checks

    try {
    some_function_that_might_die();
    }
    catch (My::Error $e) {
    # handle error
    }

    Even Better Checks

    try {
    some_function_that_might_die();
    }
    catch (HTTP::Error $e
    where { $e->code == 404 }) {
    # handle 404 error
    }

    Multiple Checks

    try {
    some_function_that_might_die();
    }
    catch (HTTP::Error $e where { $e->code == 404 }) {
    # handle 404 error
    }
    catch (HTTP::Error $e where { $e->code == 500 }) {
    # handle 500 error
    }
    catch (HTTP::Error $e) {
    # handle other HTTP error
    }
    catch ($e) {
    # handle other error
    }

    More Information

    perldoc TryCatch

    See also Try::Tiny

    Moose

    Moose

    A complete modern object system for Perl 5

    Based on Perl 6 object model

    Built on top of Class::MOPMOP - Meta Object Protocol

    Set of abstractions for components of an object system

    Classes, Objects, Methods, Attributes

    An example might help

    Moose Example

    package Point;
    use Moose;

    has 'x' => (isa => 'Int',
    is => 'ro');
    has 'y' => (isa => 'Int',
    is => 'rw');

    sub clear {
    my $self = shift;
    $self->{x} = 0;
    $self->y(0);
    }

    Understanding Moose

    There's a lot going on here

    use MooseLoads Moose environment

    Makes our class a subclass of Moose::Object

    Turns on strict and warnings

    Creating Attributes

    has 'x' => (isa => 'Int',
    is => 'ro')Creates an attribute called 'x'

    Constrainted to be an integer

    Read-only accessor

    has 'y' => (isa => 'Int',
    is => 'rw')

    Defining Methods

    sub clear {
    my $self = shift;
    $self->{x} = 0;
    $self->y(0);
    }

    Standard method syntax

    Uses generated method to set y

    Direct hash access for x

    Subclassing

    package Point3D;
    use Moose;

    extends 'Point';

    has 'z' => (isa => 'Int');

    after 'clear' => sub {
    my $self = shift;
    $self->{z} = 0;
    };

    Subclasses

    extends 'Point'Similar to use base

    Overwrites @ISA instead of appending

    has 'z' => (isa = 'Int')Adds new attribute 'z'

    No accessor function - private attribute

    Extending Methods

    after 'clear' => sub {
    my $self = shift;
    $self->{z} = 0;
    };

    New clear method for subclass

    Called after method for superclass

    Cleaner than $self->SUPER::clear()

    Creating Objects

    Moose classes are used just like any other Perl class

    $point = Point->new(x => 1, y => 2);

    $p3d = Point3D->new(x => 1,
    y => 2,
    z => 3);

    More About Attributes

    Use the has keyword to define your class's attributes

    has 'first_name' => ( is => 'rw' );

    Use is to define rw or ro

    Omitting is gives an attribute with no accessors

    Getting & Setting

    By default each attribute creates a method of the same name.

    Used for both getting and setting the attribute

    $dave->first_name('Dave');

    say $dave->first_name;

    Change Accessor Name

    Change accessor names using reader and writer

    has 'name' => (
    is => 'rw',
    reader => 'get_name',
    writer => 'set_name',
    );

    See also MooseX::FollowPBP

    Required Attributes

    Moose class attributes are optional

    Change this with required

    has 'name' => (
    is => 'ro',
    required => 1,
    );

    Forces constructor to expect a name

    Although that name could be undef

    Attribute Defaults

    Set a default value for an attribute with default

    has 'size' => (
    is => 'rw',
    default => 'medium',
    );

    Can use a subroutine reference

    has 'size' => (
    is => 'rw',
    default => \&rand_size,
    );

    Attribute Properties

    lazyOnly populate attribute when queried

    triggerSubroutine called after the attribute is set

    isaSet the type of an attribute

    Many more

    More Moose

    Many more options

    Support for concepts like delegation and roles

    Powerful plugin supportMooseX::*

    Lots of work going on in this area

    autodie

    More on Exceptions

    Exceptions force callers to deal with error conditions

    But you have to explicitly code to throw exceptions

    open my $fh, 'args->[-1], "\n";
    warn 'File: ', $e->file, "\n";
    warn 'Function: ', $e->function, "\n";
    warn 'Package: ', $e->package, "\n";
    warn 'Caller: ', $e->caller, "\n";
    warn 'Line: ', $e->line, "\n";
    }

    Nicer Errors Too

    $ perl -Mautodie -E'open my $fh, "not-there"'
    Can't open($fh, 'not-there'): No such file or directory at -e line 1

    More Information

    perldoc Fatal

    perldoc autodie

    autodie - The art of Klingon Programming http://perltraining.com.au/tips/2008-08-20.html

    Catalyst

    MVC Frameworks

    MVC frameworks are a popular way to write applicationsParticularly web applications

    M, V and C

    ModelData storage & data access

    ViewData presentation layer

    ControllerBusiness logic to glue it all together

    MVC Examples

    Ruby on Rails

    Django (Python)

    Struts (Java)

    CakePHP

    Many examples in most languages

    Perl has many options

    MVC in Perl

    MaypoleThe original Perl MVC framework

    CGI::ApplicationSimple MVC for CGI programming

    JiftyDeveloped and used by Best Practical

    CatalystCurrently the popular choice

    Newer MVC in Perl

    Dancer

    Squatting

    Mojolicious

    Catalyst

    MVC framework in Perl

    Building on other heavily-used tools

    Model uses DBIx::Class

    View uses Template Toolkit

    These are just defaults

    Can use anything you want

    Simple Catalyst App

    Assume we already have modelCD database from DBIx::Class section

    Use catalyst.pl to create project

    $ catalyst.pl CD
    created "CD"
    created "CD/script"
    created "CD/lib"
    created "CD/root"
    ... many more ...

    What Just Happened?

    Catalyst just generated a lot of useful stuff for us

    Test web serversStandalone and FastCGI

    Configuration files

    Test stubs

    Helpers for creating models, views and controllers

    A Working Application

    We already have a working application

    $ CD/script/cd_server.pl

    ... lots of output

    [info] CD powered by Catalyst 5.7015
    You can connect to your server at http://localhost:3000

    Of course, it doesn't do much yet

    Simple Catalyst App

    Next Steps

    Use various helper programs to create models and views for your application

    Write controller code to tie it all together

    Many plugins to handle various parts of the processAuthentication

    URL resolution

    Session handling

    etc...

    Create a View

    $ script/cd_create.pl view Default TT
    exists "/home/dave/training/cdlib/CD/script/../lib/CD/View"
    exists "/home/dave/training/cdlib/CD/script/../t"
    created "/home/dave/training/cdlib/CD/script/../lib/CD/View/Default.pm"
    created "/home/dave/training/cdlib/CD/script/../t/view_Default.t"

    Remove Default Message

    In lib/CD/Controller/Root.pm

    sub index :Path :Args(0) {
    my ( $self, $c ) = @_;

    # Hello World
    $c->response_body($c->welcome_message);
    }

    Remove response_body line

    Default behaviour is to render index.tt

    Need to create that

    index.tt

    root/index.tt



    CDs



    • [% FOREACH cd IN [ 1 .. 10 ] %]
    • CD [% cd %]
      [% END %]


    New Front Page

    Adding Data

    Of course that's hard-coded data

    Need to add a model class

    And then more views

    And some controllers

    There's a lot to do

    I recommend working through a tutorial

    Easier Catalyst

    A lot of web applications do similar things

    Given a database

    Produce screens to edit the data

    Surely most of this can be automated

    It's called Catalyst::Plugin::AutoCRUD

    (Demo)

    Cat::Plugin::AutoCRUD

    Does a lot of work

    On the fly

    For every request

    No security on table updates

    So it's not right for every project

    Very impressive though

    Conclusions

    There's a lot to bear in mind when writing a web app

    Using the right framework can help

    Catalyst is the most popular Perl framework

    As powerful as any other frameworkIn any language

    Lots of work still going on

    Large team, active development

    Recommended Book

    The Definitive Guide to CatalystKieren Diment

    Matt S Trout

    PSGI/Plack

    PSGI/Plack

    PSGI is an interface between Perl web applications and web servers, and Plack is a Perl module and toolkit that contains PSGI middleware, helpers and adapters to web servers.http://plackperl.org/

    PSGI/Plack

    PSGI is a specification (based on Python's WSGI)

    Plack is a reference implementation (based on Ruby's Rack)

    The Problem

    There are many ways to write web applications

    There are many ways to write web applications in Perl

    Each is subtly different

    Hard to move an application between server architectures

    Server Architectures

    CGI

    FastCGI

    mod_perl

    etc...

    Frameworks

    There are many Perl web application frameworks

    Each creates applications in subtly different ways

    Hard to port applications between them

    The Goal

    What if we had a specification that allowed us to easily move web applications between server architectures and frameworks

    PSGI is that specification

    PSGI Application

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    PSGI Application

    A code reference

    Passed a reference to an environment hash

    Returns a reference to a three-element arrayStatus code

    Headers

    Body

    A Code Reference

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    A Code Reference

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    Environment Hash

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    Environment Hash

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    Return Array Ref

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    Return Array Ref

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ Content-Type, text/plain ],
    [ Hello World ],
    ];
    };

    Running PSGI App

    Put code in app.psgi

    Drop in into a configured PSGI-aware web server

    Browse to URL

    PSGI-Aware Server

    Plack contains a simple test server called plackup

    $ plackup app.psgi
    HTTP::Server::PSGI: Accepting connections at http://localhost:5000/

    Plack::Request

    Plack::Request turns the environment into a request object

    use Plack::Request;
    use Data::Dumper;

    my $app = sub {

    my $req = Plack::Request->new(shift);
    return [
    200,
    [ 'Content-type', 'text/plain' ],
    [ Dumper $req ],
    ];
    }

    Plack::Response

    Plack::Response builds a PSGI response object

    use Plack::Request;
    use Plack::Response;
    use Data::Dumper;

    my $app = sub {
    my $req = Plack::Request->new(shift);
    my $res = Plack::Response->new(200);
    $res->content_type('text/plain');
    $res->body(Dumper $req);
    return $res->finalize;
    }

    Middleware

    Middleware wraps around an application

    Returns another PSGI application

    Simple spec makes this easy

    Plack::Middleware::*

    Plack::Builder adds middleware configuration language

    Middleware Example

    use Plack::Builder;
    use Plack::Middleware::Runtime;

    my $app = sub {
    my $env = shift;

    return [
    200,
    [ 'Content-type', 'text/plain' ],
    [ 'Hello world' ],
    ]
    };

    builder {
    enable 'Runtime';
    $app;
    }

    Middleware Example

    $ HEAD http://localhost:5000
    200 OK
    Date: Tue, 20 Jul 2010 20:25:52 GMT
    Server: HTTP::Server::PSGI
    Content-Length: 11
    Content-Type: text/plain
    Client-Date: Tue, 20 Jul 2010 20:25:52 GMT
    Client-Peer: 127.0.0.1:5000
    Client-Response-Num: 1
    X-Runtime: 0.000050

    Middleware Example

    $ HEAD http://localhost:5000
    200 OK
    Date: Tue, 20 Jul 2010 20:25:52 GMT
    Server: HTTP::Server::PSGI
    Content-Length: 11
    Content-Type: text/plain
    Client-Date: Tue, 20 Jul 2010 20:25:52 GMT
    Client-Peer: 127.0.0.1:5000
    Client-Response-Num: 1
    X-Runtime: 0.000050

    Plack::App::*

    Ready-made solutions for common situations

    Plack::App::CGIBinCgi-bin replacement

    Plack::App::DirectoryServe files with directory index

    Plack::App::URLMapMap apps to different paths

    Plack::App::*

    Many more bundled with Plack

    Configured using Plack::Builder

    Plack::App::CGIBin

    use Plack::App::CGIBin;
    use Plack::Builder;

    my $app = Plack::App::CGIBin->new(
    root => '/var/www/cgi-bin'
    )->to_app;

    builder {
    mount '/cgi-bin' => $app;
    };

    Plack::App::Directory

    use Plack::App::Directory;

    my $app = Plack::App::Directory->new(
    root => '/home/dave/Dropbox/psgi'
    )->to_app;

    Framework Support

    Many modern Perl applications already support PSGI

    Catalyst, CGI::Application, Dancer, Jifty, Mason, Maypole, Mojolicious, Squatting, Web::Simple

    Many more

    Catalyst Support

    Catalyst::Engine::PSGI

    use MyApp;

    MyApp->setup_engine('PSGI');
    my $app = sub { MyApp->run(@_) };

    Also Catalyst::Helper::PSGI

    script/myapp_create.pl PSGI

    PSGI Server Support

    Many new web servers support PSGI

    Starman, Starlet, Twiggy, Corona, HTTP::Server::Simple::PSGI

    Perlbal::Plugin::PSGI

    PSGI Server Support

    nginx support

    mod_psgi

    Plack::Handler::Apache2

    Plack::Handler::Apache2


    SetHandler perl-script
    PerlResponseHandler Plack::Handler::Apache2
    PerlSetVar psgi_app /path/to/app.psgi

    PSGI/Plack Summary

    PSGI is a specification

    Plack is an implementation

    PSGI makes your life easier

    Most of the frameworks and server you use already support PSGI

    No excuse not to use it

    Further Information

    perldoc PSGI

    perldoc Plack

    http://plackperl.org/

    http://blog.plackperl.org/

    http://github.com/miyagawa/Plack

    #plack on irc.perl.org

    Modern Perl Summary

    Perl has changed a lot in the last five years

    Perl continues to grow and change

    Perl is not a scripting language

    Perl is a powerful and flexible programming language

    Perl is a great way to get your job done

    That's all folks

    Any questions?

    Click to edit the outline text formatSecond Outline LevelThird Outline LevelFourth Outline LevelFifth Outline LevelSixth Outline LevelSeventh Outline LevelEighth Outline LevelNinth Outline Level

    YAPC::Europe2nd August 2010