<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Michał Wojciechowski</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/" />
    <link rel="self" type="application/atom+xml" href="http://blogs.perl.org/users/michal_wojciechowski/atom.xml" />
    <id>tag:blogs.perl.org,2009-11-03:/users/michal_wojciechowski//954</id>
    <updated>2013-01-09T00:27:33Z</updated>
    <subtitle>A blog about the Perl programming language</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type Pro 4.38</generator>

<entry>
    <title>Arriba - PSGI Web Server with SPDY Support</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2013/01/arriba---psgi-web-server-with-spdy-support.html" />
    <id>tag:blogs.perl.org,2013:/users/michal_wojciechowski//954.4184</id>

    <published>2013-01-08T20:46:26Z</published>
    <updated>2013-01-09T00:27:33Z</updated>

    <summary>Having some free time during the Christmas break, I decided to give a shot at a small project that I had in mind for a while, and that was to develop a PSGI-compliant(-ish) web server with support for the SPDY...</summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p>Having some free time during the Christmas break, I decided to give a shot at a small project that I had in mind for a while, and that was to develop a <a href="https://metacpan.org/module/PSGI">PSGI</a>-compliant(-ish) web server with support for the <a href="http://dev.chromium.org/spdy">SPDY protocol</a>.</p>
<p>In case you haven’t heard of it, SPDY is a networking protocol developed at Google with a goal of reducing web page load latency. It is currently used by some of Google services (including search and Gmail) and by Twitter, and is supported natively in Firefox, Chrome, and Opera — so if you visited any of those sites with any of those browsers, it’s highly likely that your web content was transmitted by means of SPDY. An official standard for the protocol is in the works.</p>]]>
        <![CDATA[<p>There was a SPDY module on CPAN that looked promising &#8212; <a href="http://search.cpan.org/perldoc?Net::SPDY">Net::SPDY</a> by <a href="http://search.cpan.org/~lkundrak/">Lubomir Rintel</a>. While not being a complete implementation of the protocol, it seemed to be working, as I found out by playing with the sample client and server scripts included in the distribution.</p>
<p>After a few days of reading the SPDY specs, minor reverse engineering of other implementations, and blatantly copying (a lot of) code from <a href="http://search.cpan.org/perldoc?Starman">Starman</a>, I was able to put together a preforking web server operational enough to run a few simple <a href="http://perldancer.org/">Dancer</a> applications. It&#8217;s a mess and nowhere near being ready for production use, but I&#8217;m happy to share it to maybe get some feedback from you fine folks &#8212; <a href="https://github.com/odyniec/Arriba">I&#8217;ve put it up on GitHub</a>. I intend to continue working on it and hopefully one day turn it into something half-decent.</p>
<p>If you want to run it, be aware that you currently need to use the Net::SPDY module from my <a href="https://github.com/odyniec/net-spdy">forked repository</a> instead of the original one, since in the original there&#8217;s some test code that breaks normal server communication.</p>
<p>About the project name &#8212; I followed the <a href="http://search.cpan.org/~miyagawa/Starman-0.3006/lib/Starman.pm#Why_the_cute_name_instead_of_more_descriptive_namespace?_Are_you_on_drugs?">idea of using friendly names</a> like Starman and Twiggy, and since SPDY reminds me of <a href="http://en.wikipedia.org/wiki/Speedy_Gonzales">Speedy Gonzales</a>, I used a part of Speedy&#8217;s catch phrase (&#8220;¡Ándele! ¡Ándele! ¡Arriba! ¡Arriba!&#8221;). However, I know I&#8217;m terrible at naming things, so I&#8217;m open to suggestions for a better name.</p>]]>
    </content>
</entry>

<entry>
    <title>Happy Birthday Perl</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2012/12/happy-birthday-perl.html" />
    <id>tag:blogs.perl.org,2012:/users/michal_wojciechowski//954.4139</id>

    <published>2012-12-18T10:32:46Z</published>
    <updated>2012-12-18T12:16:10Z</updated>

    <summary><![CDATA[Happy 25th Birthday, Perl! I made you a card: perl -C -e'print map+(v9635 x8^unpack B8).(v10)[++$n%9],(unpack u,"MK__^=^WW_S_WK)FNO\$3F5U\$7BJJ.=&gt;U51S-WK)GNM&gt;UF=W%[K[N&gt;?___SW__")=~/./g'...]]></summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p>Happy 25th Birthday, Perl! I made you a card:</p>

<pre><code>perl -C -e'print map+(v9635 x8^unpack B8).(v10)[++$n%9],(unpack u,"MK__^=^WW_S_WK)FNO\$3F5U\$7BJJ.=&gt;U51S-WK)GNM&gt;UF=W%[K[N&gt;?___SW__")=~/./g'
</code></pre>
]]>
        

    </content>
</entry>

<entry>
    <title>Building a Search Web App with Dancer and Sphinx</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2012/12/building-a-search-web-app-with-dancer-and-sphinx.html" />
    <id>tag:blogs.perl.org,2012:/users/michal_wojciechowski//954.4129</id>

    <published>2012-12-14T12:43:57Z</published>
    <updated>2012-12-14T14:16:19Z</updated>

    <summary>In this article, we&apos;ll develop a basic search application using Dancer and Sphinx. Sphinx is an open source search engine that&apos;s fairly easy to use, but powerful enough to be deployed in high-traffic sites, such as Craigslist and Dailymotion. In...</summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    <category term="dancer" label="Dancer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p>In this article, we'll develop a basic search application using Dancer and
<a href="http://sphinxsearch.com/">Sphinx</a>. Sphinx is an open source search engine
that's fairly easy to use, but powerful enough to be deployed in high-traffic
sites, such as Craigslist and Dailymotion.</p>
<p>In keeping with this year's Dancer Advent Calendar trend, the example app will
be built on Dancer 2, but it should work just as well with Dancer 1.</p>
<p>Alright, let's get to work.</p>
]]>
        <![CDATA[<h2><a name="the_data"></a>The Data</h2>

<p>Our web application will be used to search through documents stored in a MySQL
database. We'll use a simple table with the following structure:</p>
<pre class="prettyprint">CREATE TABLE documents (
    id int NOT NULL AUTO_INCREMENT,
    title varchar(200) NOT NULL,
    contents_text text NOT NULL,
    contents_html text NOT NULL,
    PRIMARY KEY (id)
);</pre>

<p>Each document has an unique ID, a title, and contents, stored as both plain text
and as HTML. We need the two formats for different purposes -- HTML will be used
to display the document in the browser, while plain text will be fed to the
indexing mechanism of the search engine (because we do not want to index the
HTML tags, obviously).</p>
<p>We can populate the database with any kind of document data -- for my test
version, I used a simple script to fill the database with POD documentation
extracted from Dancer distribution. The script is included at the end of this
article, in case you'd like to use it yourself.</p>
<h2><a name="installation_and_configuration_of_sphinx"></a>Installation and Configuration of Sphinx</h2>

<p>Sphinx can be installed pretty easily, using one of the pre-compiled <code>.rpm</code> or
<code>.deb</code> packages, or the source tarball. These are available at the <a href="http://sphinxsearch.com/downloads/release/">download
page at SphinxSearch.com</a> -- grab the
one that suits you and follow the <a href="http://sphinxsearch.com/docs/current.html#installation">installation
instructions</a>.</p>
<p>When Sphinx is installed, it needs to be configured before we can play with it.
Its main configuration file is usually located at <code>/etc/sphinx/sphinx.conf</code>.
For our purposes, a very basic setup will do -- we'll put the following in the
<code>sphinx.conf</code> file:</p>
<pre class="prettyprint">source documents
{
    type        = mysql
    sql_host    = localhost
    sql_user    = user
    sql_pass    = hunter1
    sql_db      = docs

    sql_query   = \
        SELECT id, title, contents_text FROM documents
}

index test
{
    source          = documents
    charset_type    = utf-8
    path            = /usr/local/sphinx/data/test
}</pre>

<p>This defines one <i>source</i>, which is what Sphinx uses to gather data, and one
<i>index</i>, which will be created by processing the collected data and will then
be queried when we perform the searches. In our case, the source is the
documents database that we just created. The <code>sql_query</code> directive defines the
<code>SELECT</code> query that Sphinx will use to pull the data, and it includes all the
fields from the <code>documents</code> table, except <code>contents_html</code> -- like we said,
HTML is not supposed to be indexed.</p>
<p>That's all that we need to start using Sphinx. After we make sure the <code>searchd</code>
daemon is running, we can proceed with indexing the data. We call <code>indexer</code>
with the name of the index:</p>
<pre class="prettyprint">$ indexer test</pre>

<p>It should spit out some information about the indexing operation, and when it's
done, we can do our first search:</p>
<pre class="prettyprint">$ search "plugin"

index 'test': query 'plugin ': returned 8 matches of 8 total in 0.002 sec

displaying matches:
1. document=19, weight=2713
2. document=44, weight=2694
3. document=20, weight=1713
4. document=2, weight=1672
5. document=1, weight=1640
6. document=13, weight=1640
7. document=27, weight=1601
8. document=28, weight=1601</pre>

<p>Apparently, there are 8 documents in the Dancer documentation with the word
<i>plugin</i>, and the one with the ID of 19 is the highest ranking result. Let's
see which document that is:</p>
<pre class="prettyprint">mysql&gt; SELECT title FROM documents WHERE id = 19;
+----------------------------------------------------+
| title                                              |
+----------------------------------------------------+
| Dancer::Plugin - helper for writing Dancer plugins |
+----------------------------------------------------+</pre>

<p>It's the documentation for <a href="https://metacpan.org/module/Dancer::Plugin">Dancer::Plugin</a>, and it makes total sense that this
is the first result for the word <i>plugin</i>. Sphinx setup is thus ready and we
can get to the web application part of our little project.</p>
<h2><a name="the_basic_application"></a>The Basic Application</h2>

<p>We'll start with a simple web application (let's call it <code>DancerSearch</code>) that
just shows a search form, and then we'll extend it with more features. It will
be using Dancer 2.0, and the <a href="https://metacpan.org/module/Dancer::Plugin::Database">Dancer::Plugin::Database</a> plugin (we'll use it to
access the documents database). The code below is the initial
<code>lib/DancerSearch.pm</code> file:</p>
<pre class="prettyprint">package DancerSearch;

use Dancer 2.0;
use Dancer::Plugin::Database;

get '/' =&gt; sub {
    template 'index';
};

1;</pre>

<p>We're also going to need a little startup script, <code>bin/app.pl</code>:</p>
<pre class="prettyprint">#!/usr/bin/env perl

use Dancer 2.0;
use DancerSearch;

start;</pre>

<p>And a simple layout -- <code>views/layouts/main.tt</code>:</p>
<pre class="prettyprint">&lt;!doctype html&gt;
&lt;html&gt;
    &lt;head&gt;
    &lt;title&gt;Dancer Search Engine&lt;/title&gt;
    &lt;link rel="stylesheet" href="css/style.css"&gt;
    &lt;/head&gt;
    &lt;body&gt;
    &lt;h1&gt;Dancer Search Engine&lt;/h1&gt;
    &lt;div id="content"&gt;
        [% content %]
    &lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</pre>

<p>And, of course, a template for our index page. For now it'll just contain a
search form -- <code>views/index.tt</code>:</p>
<pre class="prettyprint">&lt;form action="/" method="get"&gt;
    Search query:
    &lt;input type="text" name="query"&gt;
    &lt;input type="submit" value="Search"&gt;
&lt;/form&gt;</pre>

<p>Last but not least, we need a configuration file to tell our app which layout we
want to use, and how to connect to our documents database using the
Dancer::Plugin::Database plugin. This goes into <code>config.yml</code>:</p>
<pre class="prettyprint">layout: main

plugins:
    Database:
        driver:     mysql
        host:       localhost
        database:   docs
        username:   user
        password:   hunter1</pre>

<p>We can now launch the application, and it will greet us with a search form.
Which, unsurprisingly, doesn't work yet. Let's wire it up to Sphinx.</p>
<h2><a name="the_sphinx__search_cpan_module"></a>The Sphinx::Search CPAN Module</h2>

<p>There is a CPAN module called <a href="https://metacpan.org/module/Sphinx::Search">Sphinx::Search</a> that provides a Perl interface
to Sphinx, and we're going to use it in our app. We put <code>use Sphinx::Search</code> in
<code>DancerSearch.pm</code>, and add the following piece of code before the <code>get '/'</code>
route handler:</p>
<pre class="prettyprint"># Create a new Sphinx::Search instance
my $sph = Sphinx::Search-&gt;new;
# Match all words, sort by relevance, return the first 10 results
$sph-&gt;SetMatchMode(SPH_MATCH_ALL);
$sph-&gt;SetSortMode(SPH_SORT_RELEVANCE);
$sph-&gt;SetLimits(0, 10);</pre>

<p>This creates a new instance of Sphinx::Search (which will be used to talk to the
Sphinx daemon and do the searches), and sets up a few basic options, such as how
many results should be returned and in what order. Now comes the most
interesting part -- actually performing a search in our application. We insert
this chunk of code at the beginning of the <code>get '/'</code> route handler:</p>
<pre class="prettyprint">if (my $phrase = params('query')-&gt;{'phrase'}) {
    # Send the search query to Sphinx
    my $results = $sph-&gt;Query($phrase);

    my $retrieved_count = 0;
    my $total_count;
    my $documents = [];

    if ($total_count = $results-&gt;{'total_found'}) {
        $retrieved_count = @{$results-&gt;{'matches'}};
        # Get the array of document IDs
        my @document_ids = map { $_-&gt;{'doc'} } @{$results-&gt;{'matches'}};
        # Join the IDs to use in SQL query (the IDs come from Sphinx, so we
        # can trust them to be safe)
        my $ids_joined = join ',', @document_ids;

        # Select documents, in the same order as returned by Sphinx
        # (the contents of $ids_joined comes from Sphinx)
        my $sth = database-&gt;prepare('SELECT id, title FROM documents ' .
            "WHERE id IN ($ids_joined) ORDER BY FIELD(id, $ids_joined)");
        $sth-&gt;execute;

        # Fetch all results as an arrayref of hashrefs
        $documents = $sth-&gt;fetchall_arrayref({});
    }

    # Show search results page
    return template 'index', {
        phrase =&gt; encode_entities($phrase),
        retrieved_count =&gt; $retrieved_count,
        total_count =&gt; $total_count,
        documents =&gt; $documents
    };
}</pre>

<p>Let's go through what is happening here. First, we check if there was actually a
search phrase in the query string (<code>params('query')-&gt;{'phrase'}</code>). If there
was one, we pass it to the <code>$sph-&gt;Query()</code> method, which queries Sphinx and
returns the search results (the returned data structure is briefly explained in
the description of the Query method in Sphinx::Search documentation).</p>
<p>We then check the number of results (<code>$results-&gt;{'total_found'}</code>), and if
it's greater than zero, it means we found something and we need to retrieve the
documents data from the database. Sphinx only returns the IDs of the matching
documents (as shown earlier in the test search that we did using the command
line), so we need to send a query to the database to get the actual data, such
as document titles that we want to display in the results (note that we're using
the <code>ORDER BY FIELD</code> construct in the <code>SELECT</code> query to maintain the same
order as the list returned by Sphinx).</p>
<p>When we have the documents data ready, we pass it along with other information
(such as the total number of results) to be displayed in our index template.
But, hold on a second -- the template is not yet ready to display the results,
it only shows the search form. Let's fix that now -- below the search form, we
add the following code:</p>
<pre class="prettyprint">[% IF phrase %]
    &lt;p&gt;Search results for &lt;strong&gt;&amp;quot;[% phrase %]&amp;quot;&lt;/strong&gt;&lt;/p&gt;

    [% IF total_count %]
    &lt;p&gt;
        Found [% total_count %] hits.
        Showing results 1 - [% retrieved_count %].
    &lt;/p&gt;

    &lt;ol&gt;
    [% FOREACH document IN documents %]
        &lt;li&gt;
            &lt;a href="/document/[% document.id %]"&gt;[% document.title %]&lt;/a&gt;
        &lt;/li&gt;
    [% END %]
    &lt;/ol&gt;
    [% ELSE %]    
    &lt;p&gt;
        No hits -- try again!
    &lt;/p&gt;
    [% END %]
[% END %]</pre>

<p>This displays the phrase that was submitted, the number of hits, and a list of
results (or a "no hits" message if there weren't any).</p>
<p>And you know what? We're now ready to actually do a search in the browser:</p>
<img alt="search-results.png" src="http://blogs.perl.org/users/michal_wojciechowski/2012/12/14/search-results.png/search-results.png" width="590" height="350" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /><p>Neat, we have a working search application! We're just missing one important
thing, and that is being able to access a document that was found. The results
link to <code>/document/:document_id</code>, but that route isn't recognized by our app.
No worries, we can fix that easily:</p>
<pre class="prettyprint"># Get the document with the specified ID
get '/document/:id' =&gt; sub {
    my $sth = database-&gt;prepare('SELECT contents_html FROM documents ' .
        'WHERE id = ?');
    $sth-&gt;execute(params-&gt;{'id'});
        
    if (my $document = $sth-&gt;fetchrow_hashref) {
        return $document-&gt;{'contents_html'};
    }
    else {
        status 404;
        return "Document not found";
    }
};</pre>

<p>This route handler is pretty straightforward, we grab the ID from the URL, use
it in a <code>SELECT</code> query to the documents table, and return the HTML contents of
the matching document (or a 404 page, if there's no document with that ID).</p>
<h2><a name="the_complete_application"></a>The Complete Application</h2>

<p>This is the complete <code>DancerSearch.pm</code> file:</p>
<pre class="prettyprint">package DancerSearch;

use Dancer 2.0;
use Dancer::Plugin::Database;
use HTML::Entities qw( encode_entities );
use Sphinx::Search;

# Create a new Sphinx::Search instance
my $sph = Sphinx::Search-&gt;new;
# Match all words, sort by relevance, return the first 10 results
$sph-&gt;SetMatchMode(SPH_MATCH_ALL);
$sph-&gt;SetSortMode(SPH_SORT_RELEVANCE);
$sph-&gt;SetLimits(0, 10);

get '/' =&gt; sub {
    if (my $phrase = params('query')-&gt;{'phrase'}) {
        # Send the search query to Sphinx
        my $results = $sph-&gt;Query($phrase);

        my $retrieved_count = 0;
        my $total_count;
        my $documents = [];

        if ($total_count = $results-&gt;{'total_found'}) {
            $retrieved_count = @{$results-&gt;{'matches'}};
            # Get the array of document IDs
            my @document_ids = map { $_-&gt;{'doc'} } @{$results-&gt;{'matches'}};
            # Join the IDs to use in SQL query (the IDs come from Sphinx, so we
            # can trust them to be safe)
            my $ids_joined = join ',', @document_ids;

            # Select documents, in the same order as returned by Sphinx
            my $sth = database-&gt;prepare('SELECT id, title FROM documents ' .
                "WHERE id IN ($ids_joined) ORDER BY FIELD(id, $ids_joined)");
            $sth-&gt;execute;

            # Fetch all results as an arrayref of hashrefs
            $documents = $sth-&gt;fetchall_arrayref({});
        }

        # Show search results page
        return template 'index', {
            phrase =&gt; encode_entities($phrase),
            retrieved_count =&gt; $retrieved_count,
            total_count =&gt; $total_count,
            documents =&gt; $documents
        };
    }
    else {
        # No search phrase -- show just the search form
        template 'index';
    }
};

# Get the document with the specified ID
get '/document/:id' =&gt; sub {
    my $sth = database-&gt;prepare('SELECT contents_html FROM documents ' .
        'WHERE id = ?');
    $sth-&gt;execute(params-&gt;{'id'});
        
    if (my $document = $sth-&gt;fetchrow_hashref) {
        return $document-&gt;{'contents_html'};
    }
    else {
        status 404;
        return "Document not found";
    }
};

1;</pre>

<h2><a name="conclusion"></a>Conclusion</h2>

<p>What we've built is still a very basic application, lacking many features -- the
most obvious one that's missing is pagination, and being able to access results
further down the list, not just the first ten. However, the code can be easily
extended, thanks to the flexibility and ease of use of both Dancer and Sphinx.
With a bit of effort, it can be made into an useful search app for a knowledge
base site, or a wiki.</p>
<p>I think this application is a good example of how Dancer benefits from being
part of the Perl ecosystem, giving web developers the ability to make use of the
thousands of modules in CPAN (like we just did with Sphinx::Search). This allows
to build working prototypes of web applications and implement complex features
in a very short time.</p>
<h2><a name="the_pod_extraction_script"></a>The POD Extraction Script</h2>

<p>As promised, this is the script that I used to extract the POD from Dancer
distribution and store it in the MySQL database:</p>
<pre class="prettyprint">#!/usr/bin/env perl

package MyParser;

use strict;
use vars qw(@ISA);

use Pod::Simple::PullParser ();
BEGIN { @ISA = ('Pod::Simple::PullParser') }

use DBI;
use File::Find;
use Pod::Simple::Text;
use Pod::Simple::HTML;

# Variables to hold the text and HTML produced by POD parsers
my ($text, $html);
# Create parser objects and tell them where their output will go
(my $parser_text = Pod::Simple::Text-&gt;new)-&gt;output_string(\$text);
(my $parser_html = Pod::Simple::HTML-&gt;new)-&gt;output_string(\$html);

# Initialize database connection
my $dbh = DBI-&gt;connect("dbi:mysql:dbname=docs;host=localhost", "user",
    "hunter1")
    or die $!;

sub run {
    my $self = shift;
    my (@tokens, $title);

    while (my $token = $self-&gt;get_token) {
        push @tokens, $token;

        # We're looking for a "=head1 NAME" section
        if (@tokens &gt; 5) {
            if ($tokens[0]-&gt;is_start &amp;&amp; $tokens[0]-&gt;tagname eq 'head1' &amp;&amp;
                $tokens[1]-&gt;is_text &amp;&amp; $tokens[1]-&gt;text =~ /^name$/i &amp;&amp;
                $tokens[4]-&gt;is_text)
            {
                $title = $tokens[4]-&gt;text;
                # We have the title, so we can ignore the remaining tokens
                last;
            }

            shift @tokens;
        }
    }

    # No title means no POD -- we're done with this file
    return if !$title;

    print "Adding: $title\n";

    $parser_text-&gt;parse_file($self-&gt;source_filename);
    $parser_html-&gt;parse_file($self-&gt;source_filename);

    # Add the new document to the database
    $dbh-&gt;do("INSERT INTO documents (title, contents_text, " .
        "contents_html) VALUES(?, ?, ?)", undef, $title, $text, $html);

    # Clear the content variables and reinitialize parsers
    $text = $html = "";
    $parser_text-&gt;reinit;
    $parser_html-&gt;reinit;
}

my $parser = MyParser-&gt;new;

find({ wanted =&gt; sub {
    if (-f and /\.pm$|\.pod$/) {
        $parser-&gt;parse_file($File::Find::name);
        $parser-&gt;reinit;
    }
}, no_chdir =&gt; 1 }, shift || '.');</pre>

<p>You can run it with one argument, which is the location of the directory that
will be scanned (recursively) for .pm/.pod files, or with no arguments, in which
case the script will work with the current directory.</p>
<p>(Note: The script makes use of <a href="https://metacpan.org/module/Pod::Simple">Pod::Simple</a>, which I'm not very familiar with,
so it's possible that I'm doing something stupid with it -- if that's the case,
please let me know.)</p><p><i>This post was <a href="http://advent.perldancer.org/2012/14">originally published</a> as part of the <a href="http://advent.perldancer.org/2012">2012 Dancer Advent Calendar</a>.</i></p>]]>
    </content>
</entry>

<entry>
    <title>Let Paths Be Paths Again</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2012/02/let-paths-be-paths-again.html" />
    <id>tag:blogs.perl.org,2012:/users/michal_wojciechowski//954.2873</id>

    <published>2012-02-26T22:29:31Z</published>
    <updated>2012-02-26T22:41:26Z</updated>

    <summary><![CDATA[The de facto standard way of constructing portable filesystem paths in Perl is through the use of File::Spec's catfile and catdir functions. Example: my $path = File::Spec-&gt;catfile('dir', 'subdir', 'file.txt'); This method, or a similar one involving Path::Class, is the most...]]></summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p>The de facto standard way of constructing portable filesystem paths in Perl is through the use of <a href="http://search.cpan.org/perldoc?File%3A%3ASpec">File::Spec</a>'s <a href="http://search.cpan.org/perldoc?File%3A%3ASpec#catfile">catfile</a> and <a href="http://search.cpan.org/perldoc?File%3A%3ASpec#catdir">catdir</a> functions. Example:</p>

<pre>my $path = File::Spec-&gt;catfile('dir', 'subdir', 'file.txt');</pre>

<p>This method, or a similar one involving <a href="http://search.cpan.org/dist/Path-Class">Path::Class</a>, is the most recommended approach and has been adopted by application development frameworks like <a href="http://perldancer.org/">Dancer</a> (which has a wrapper method for it, named <a href="http://search.cpan.org/%7Exsawyerx/Dancer/lib/Dancer.pm#path"><code>path</code></a>) and <a href="http://www.catalystframework.org/">Catalyst</a> (with its <a href="http://search.cpan.org/%7Emstrout/Catalyst-Runtime/lib/Catalyst.pm#$c-%3Epath_to%28@path%29"><code>path_to</code></a> method).</p>

<p>The slight problem that I see with this method is that it makes code a bit more complicated, and thus a bit less readable. Paths become lists of parameters and no longer <i>look</i> like paths.</p>

<p>I wrote a simple module that tries to address this by allowing you to write paths the traditional way -- as strings, using a directory separator of your choice (<code>/</code> being the default), while the <code>catfile</code> stuff happens behind the scenes. You can just say:</p>

<pre>my $path = path 'dir/subdir/file.txt';</pre>

<p>What it does is it splits the path string on each occurrence of the forward slash and feeds the resulting list of path components to <code>File::Spec-&gt;catfile</code>, which reassembles them using the appropriate OS-specific directory separator, and constructs the OS-specific path that you want.</p>

<p>The module is up <a href="https://github.com/odyniec/File-PlainPath">on Github</a>, and should also be available on CPAN shortly.</p>]]>
        <![CDATA[<br />]]>
    </content>
</entry>

<entry>
    <title>Perldoc and I Would Like to Wish You a...</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2011/12/perldoc-and-i-would-like-to-wish-you-a.html" />
    <id>tag:blogs.perl.org,2011:/users/michal_wojciechowski//954.2607</id>

    <published>2011-12-24T12:48:14Z</published>
    <updated>2011-12-24T12:51:55Z</updated>

    <summary>perldoc perlsyn | perl -ne &apos;s/^.*?&quot;|\\.*$//g,print if/1\.\.15/&apos;...</summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p><code>perldoc perlsyn | perl -ne 's/^.*?"|\\.*$//g,print if/1\.\.15/'</code></p>
]]>
        

    </content>
</entry>

<entry>
    <title>Alternative Dancer Templating Engines</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2011/12/alternative-dancer-templating-engines.html" />
    <id>tag:blogs.perl.org,2011:/users/michal_wojciechowski//954.2583</id>

    <published>2011-12-18T13:59:47Z</published>
    <updated>2011-12-18T21:56:26Z</updated>

    <summary>Dancer uses a simple model of interfacing with templating engines (based on Dancer::Template::Abstract) and makes it very easy to add support for new engines. Thanks to this, if you&apos;re not happy with the default simple engine or with Template Toolkit,...</summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    <category term="dancer" label="Dancer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p>Dancer uses a simple model of interfacing with templating engines (based on
<a href="http://search.cpan.org/perldoc?Dancer::Template::Abstract">Dancer::Template::Abstract</a>) and makes it very easy to add support for new
engines. Thanks to this, if you're not happy with the default <code>simple</code> engine
or with <a href="http://template-toolkit.org/index.html">Template Toolkit</a>, there is now
a dozen different alternatives to choose from. Let's take a look at some of
them.</p>
<h2><a href="editor-content.html?cs=utf-8" name="dancer__template__tiny"></a></h2>]]>
        <![CDATA[<h2>Dancer::Template::Tiny</h2>

<p><a href="http://search.cpan.org/perldoc?Template::Tiny">Template::Tiny</a> is a lightweight engine which reimplements a subset of
Template Toolkit features. As the name implies, it aims to accomplish this with
as little code as possible. If you're using just the basic functionality of
Template Toolkit, you should be able to switch to Template::Tiny without any
modifications to template files (and you can easily go back at any moment).</p>
<p><a href="http://search.cpan.org/perldoc?Dancer::Template::Tiny">Dancer::Template::Tiny</a> is going to replace <a href="http://search.cpan.org/perldoc?Dancer::Template::Simple">Dancer::Template::Simple</a> as the
default templating engine in Dancer2.</p>
<p>Example template:</p>
<pre class="prettyprint"><span class="pun">&lt;</span><span class="tag">html</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;</span><span class="tag">head</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">title</span><span class="pun">&gt;</span><span class="pln">Tiny Example</span><span class="pun">&lt;/</span><span class="tag">title</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"[% request.uri_base %]/css/style.css"</span><span class="pln"> </span><span class="pun">/&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;/</span><span class="tag">head</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;</span><span class="tag">body</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">h1</span><span class="pun">&gt;</span><span class="pln">Hello, World! This is Dancer [% dancer_version %]!</span><span class="pun">&lt;/</span><span class="tag">h1</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">p</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; [% IF morning %]<br />&nbsp; &nbsp; &nbsp; &nbsp; Good morning!<br />&nbsp; &nbsp; &nbsp; [% ELSE %]<br />&nbsp; &nbsp; &nbsp; &nbsp; Good afternoon!<br />&nbsp; &nbsp; &nbsp; [% END %] <br />&nbsp; &nbsp; </span><span class="pun">&lt;/</span><span class="tag">p</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;/</span><span class="tag">body</span><span class="pun">&gt;</span><span class="pln"><br /></span><span class="pun">&lt;/</span><span class="tag">html</span><span class="pun">&gt;</span></pre>

<p>Route handler:</p>
<pre class="prettyprint"><span class="kwd">use</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">;</span><span class="pln"><br />&nbsp; &nbsp; <br /></span><span class="kwd">get</span><span class="pln"> </span><span class="str">'/hello'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">sub</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="kwd">template</span><span class="pln"> </span><span class="str">'hello'</span><span class="pun">,</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> morning </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="pun">(</span><span class="pln">localtime</span><span class="pun">)[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">12</span><span class="pun">,</span><span class="pln"> now </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">-&gt;</span><span class="pln">now </span><span class="pun">};</span><span class="pln"><br /></span><span class="pun">};</span></pre>

<h2><a href="editor-content.html?cs=utf-8" name="dancer__template__tenjin"></a>Dancer::Template::Tenjin</h2>

<p><a href="http://www.kuwata-lab.com/tenjin/">Tenjin</a> is a very fast templating engine
with implementations for many languages -- including, of course, Perl. Its great
performance comes from the fact that it uses the underlying language's
constructs to process templates, instead of defining its own templating language
and having to parse it. Support for this engine in Dancer is provided by 
<a href="http://search.cpan.org/perldoc?Dancer::Template::Tenjin">Dancer::Template::Tenjin</a>.</p>
<p>Example template:</p>
<pre class="prettyprint"><span class="pun">&lt;</span><span class="tag">html</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;</span><span class="tag">head</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">title</span><span class="pun">&gt;</span><span class="pln">Tenjin Example</span><span class="pun">&lt;/</span><span class="tag">title</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">link</span><span class="pln"> </span><span class="atn">rel</span><span class="pun">=</span><span class="atv">"stylesheet"</span><span class="pln"> </span><span class="atn">href</span><span class="pun">=</span><span class="atv">"[== $request-&gt;</span><span class="pln">uri_base =]/css/style.css" /&gt;<br />&nbsp; </span><span class="pun">&lt;/</span><span class="tag">head</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;</span><span class="tag">body</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">h1</span><span class="pun">&gt;</span><span class="pln">Hello, World! This is Dancer [= $dancer_version =]!</span><span class="pun">&lt;/</span><span class="tag">h1</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">p</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; </span><span class="pun">&lt;?</span><span class="pln">pl </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">localtime</span><span class="pun">)[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; &nbsp; Good morning!<br />&nbsp; &nbsp; &nbsp; </span><span class="pun">&lt;?</span><span class="pln">pl </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; &nbsp; Good afternoon!<br />&nbsp; &nbsp; &nbsp; </span><span class="pun">&lt;?</span><span class="pln">pl </span><span class="pun">}</span><span class="pln"> </span><span class="pun">?&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;/</span><span class="tag">p</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">&lt;</span><span class="tag">p</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; Current time is: [== DateTime-&gt;now-&gt;hms =]<br />&nbsp; &nbsp; </span><span class="pun">&lt;/</span><span class="tag">p</span><span class="pun">&gt;</span><span class="pln"><br />&nbsp; </span><span class="pun">&lt;/</span><span class="tag">body</span><span class="pun">&gt;</span><span class="pln"><br /></span><span class="pun">&lt;/</span><span class="tag">html</span><span class="pun">&gt;</span></pre>

<p>Route handler:</p>
<pre class="prettyprint"><span class="kwd">use</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">;</span><span class="pln"><br />&nbsp; &nbsp; <br /></span><span class="kwd">get</span><span class="pln"> </span><span class="str">'/hello'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">sub</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="kwd">template</span><span class="pln"> </span><span class="str">'hello'</span><span class="pun">;</span><span class="pln"><br /></span><span class="pun">};</span></pre>

<h2><a href="editor-content.html?cs=utf-8" name="dancer__template__haml"></a>Dancer::Template::Haml</h2>

<p><a href="http://haml-lang.com/">Haml</a>, which stands for "HTML Abstraction Markup
Language", brings a fresh, different approach to templating. It aims at making
templates short, clean, and as easy to read as well-formatted source code.
<a href="http://search.cpan.org/perldoc?Dancer::Template::Haml">Dancer::Template::Haml</a> is a wrapper around <a href="http://search.cpan.org/perldoc?Text::Haml">Text::Haml</a> and lets you use
Haml templates in Dancer applications.</p>
<p>Example template:</p>
<pre class="prettyprint"><span class="pun">%</span><span class="pln">html<br />&nbsp; </span><span class="pun">%</span><span class="pln">head<br />&nbsp; &nbsp; </span><span class="pun">%</span><span class="pln">title </span><span class="typ">Haml</span><span class="pln"> </span><span class="typ">Example</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">%</span><span class="pln">link</span><span class="pun">(</span><span class="pln">rel</span><span class="pun">=</span><span class="str">"stylesheet"</span><span class="pln"> href</span><span class="pun">=</span><span class="str">"#{$request-&gt;uri_base}/css/style.css"</span><span class="pun">)</span><span class="pln"><br />&nbsp; </span><span class="pun">%</span><span class="pln">body<br />&nbsp; &nbsp; </span><span class="pun">%</span><span class="pln">h1 </span><span class="typ">Hello</span><span class="pun">,</span><span class="pln"> </span><span class="typ">World</span><span class="pun">!</span><span class="pln"> </span><span class="typ">This</span><span class="pln"> </span><span class="kwd">is</span><span class="pln"> </span><span class="typ">Dancer</span><span class="pln"> </span><span class="com">#{$dancer_version}!</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="pun">%</span><span class="pln">p<br />&nbsp; &nbsp; &nbsp; </span><span class="pun">-</span><span class="pln"> </span><span class="kwd">if</span><span class="pln"> </span><span class="pun">((</span><span class="pln">localtime</span><span class="pun">)[</span><span class="lit">2</span><span class="pun">]</span><span class="pln"> </span><span class="pun">&lt;</span><span class="pln"> </span><span class="lit">12</span><span class="pun">)</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="typ">Good</span><span class="pln"> morning</span><span class="pun">!</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; </span><span class="pun">-</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> </span><span class="kwd">else</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; &nbsp; </span><span class="typ">Good</span><span class="pln"> afternoon</span><span class="pun">!</span><span class="pln"><br />&nbsp; &nbsp; &nbsp; </span><span class="pun">-</span><span class="pln"> </span><span class="pun">}</span><span class="pln"> <br />&nbsp; &nbsp; </span><span class="pun">%</span><span class="pln">p </span><span class="typ">Current</span><span class="pln"> time </span><span class="kwd">is</span><span class="pun">:</span><span class="pln"> </span><span class="com">#{DateTime-&gt;now-&gt;hms}</span></pre>

<p>Route handler:</p>
<pre class="prettyprint"><span class="kwd">use</span><span class="pln"> </span><span class="typ">DateTime</span><span class="pun">;</span><span class="pln"><br />&nbsp; &nbsp; <br /></span><span class="kwd">get</span><span class="pln"> </span><span class="str">'/hello'</span><span class="pln"> </span><span class="pun">=&gt;</span><span class="pln"> </span><span class="kwd">sub</span><span class="pln"> </span><span class="pun">{</span><span class="pln"><br />&nbsp; &nbsp; </span><span class="kwd">template</span><span class="pln"> </span><span class="str">'hello'</span><span class="pun">;</span><span class="pln"><br /></span><span class="pun">};</span></pre>

<h2><a href="editor-content.html?cs=utf-8" name="more"></a>More</h2>

<p>There are many more interesting templating engines ready to be used with Dancer,
such as <a href="http://www.masonhq.com/">Mason</a> (provided by
<a href="http://search.cpan.org/perldoc?Dancer::Template::Mason">Dancer::Template::Mason</a>) or <a href="http://xslate.org/">Xslate</a>
(<a href="http://search.cpan.org/perldoc?Dancer::Template::Xslate">Dancer::Template::Xslate</a>). Do a <a href="http://search.cpan.org/">CPAN</a> or
<a href="https://metacpan.org/">MetaCPAN</a> search for "dancer template" to get a list of
all the available engines, and choose the one that suits you best. In the true
spirit of Perl, there's more than one way to write a template!</p><p><i>This post was <a href="http://advent.perldancer.org/2011/18">originally published</a> as part of the <a href="http://advent.perldancer.org/2011">2011 Dancer Advent Calendar</a>.</i></p>]]>
    </content>
</entry>

<entry>
    <title>Serving Files with Dancer::Plugin::DirectoryView and Dancer::Plugin::Auth::Htpasswd</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2011/12/serving-files-with-dancerplugindirectoryview-and-dancerpluginauthhtpasswd.html" />
    <id>tag:blogs.perl.org,2011:/users/michal_wojciechowski//954.2573</id>

    <published>2011-12-13T22:16:10Z</published>
    <updated>2011-12-13T22:33:32Z</updated>

    <summary>A while ago I was converting a simple PHP website to Dancer, and moving it from being deployed on Apache to Starman. There wasn&apos;t a lot of code, so rewriting went quickly -- but, the site used a few specific...</summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    <category term="dancer" label="Dancer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p>A while ago I was converting a simple PHP website to Dancer,
and moving it from being deployed on Apache to Starman.
There wasn't a lot of code,
so rewriting went quickly -- but,
the site used a few specific features of Apache,
namely directory indexes (courtesy of <a href="http://search.cpan.org/perldoc?http%3A#%2Fhttpd.apache.org%2Fdocs%2Fcurrent%2Fmod%2Fmod_autoindex.html">mod_autoindex</a>) to allow user access to directories/files on the server,
and <code>htpasswd</code> files to password-protect some of those directories.</p>

<p>I could just deploy the new Dancer website on Apache and keep using those goodies,
but I thought that it would be nice if Dancer itself provided similar features.
So,
I created two plugins that do just that: <a href="http://search.cpan.org/perldoc?Dancer%3A%3APlugin%3A%3ADirectoryView">Dancer::Plugin::DirectoryView</a> and <a href="http://search.cpan.org/perldoc?Dancer%3A%3APlugin%3A%3AAuth%3A%3AHtpasswd">Dancer::Plugin::Auth::Htpasswd</a>.
Let me now show you how to use them.</p>]]>
        <![CDATA[<h2>Directory Indexes</h2>

<p>Let's say we have a <code>files</code> directory under <code>public</code>,
and we'd like to allow users to browse it and download files.
Enabling directory access is as simple as including the plugin in our Dancer application:</p>

<pre>      package MyWebApp;

      ...

      use Dancer::Plugin::DirectoryView;</pre>

<p>And updating the configuration file (<code>config.yml</code>) to tell the plugin which directory should be made available, and at which URL:</p>

<pre>      plugins:
          DirectoryView:
              url: /pub
              root_dir: files</pre>

<p>That's it -- now, if we launch our app and point the browser at the <code>/pub</code> URL, we'll see the contents of the directory:</p>

<img alt="screenshot-1-580.png" src="http://blogs.perl.org/users/michal_wojciechowski/2011/12/13/screenshot-1-580.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" height="227" width="580" />

<h2>Protecting Directories with Htpasswd Files</h2>

<p>As you might have noticed on the screenshot, there's a <code>secret</code> directory under <code>files</code>.
 It contains some super secret data that should only be available to 
authorized users, so now we're going to protect it using a <code>htpasswd</code> file.</p>

<p>First, let's create the <code>htpasswd</code> file and an user, named "alice":</p>

<pre>      $ htpasswd -c htpasswd alice</pre>

<p>Once it is created, we need to put the <code>htpasswd</code> file in a safe location outside of the public directory, so let's create a new directory <code>passwd</code> and store the file in there.</p>

<p>(If you're migrating from Apache and already have the <code>htpasswd</code> file, you just need to copy it to your Dancer application.)</p>

<p>In our Dancer application, we include the Auth::Htpasswd plugin:</p>

<pre>      package MyWebApp;

      ...

      use Dancer::Plugin::Auth::Htpasswd;</pre>

<p>Now, we need to update our configuration file and add settings for the plugin. We'll tell it to protect the <code>/pub/secret</code> path, and to use the <code>htpasswd</code> file we just created:</p>

<pre>      plugins:
         "Auth::Htpasswd":
             paths:
                 "/pub/secret":
                     realm: "Secret Files"
                     passwd_file: passwd/htpasswd</pre>

<p>The <code>realm</code> parameter lets us set the text that will be shown to the user in the login window displayed by the browser.</p>

<p>Let's see if our protection works. We restart the application and try to access the <code>/pub/secret/</code> URL:</p><p><img alt="screenshot-2-580.png" src="http://blogs.perl.org/users/michal_wojciechowski/2011/12/13/screenshot-2-580.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" height="135" width="580" /></p>



<p>Great, our confidential files are safe. Only when we log in as "Alice", we'll be able to access them:</p><p><img alt="screenshot-3-580.png" src="http://blogs.perl.org/users/michal_wojciechowski/2011/12/13/screenshot-3-580.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" height="227" width="580" /></p><i>This post was <a href="http://advent.perldancer.org/2011/13">originally published</a> as part of the <a href="http://advent.perldancer.org/2011">2011 Dancer Advent Calendar</a>.</i>]]>
    </content>
</entry>

<entry>
    <title>GitHub-friendly README files with ExtUtils::MakeMaker and Module::Build</title>
    <link rel="alternate" type="text/html" href="http://blogs.perl.org/users/michal_wojciechowski/2011/11/github-friendly-readme-files-with-extutils-makemaker-and-module-build.html" />
    <id>tag:blogs.perl.org,2011:/users/michal_wojciechowski//954.2510</id>

    <published>2011-11-30T23:39:52Z</published>
    <updated>2012-02-28T20:25:54Z</updated>

    <summary>GitHub is a great place to host open-source projects and expose them to a wide community of developers, so it&apos;s not surprising that more and more Perl modules are making it their home. One of the features of GitHub is...</summary>
    <author>
        <name>Michał Wojciechowski</name>
        <uri>http://odyniec.net/</uri>
    </author>
    
    <category term="github" label="github" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blogs.perl.org/users/michal_wojciechowski/">
        <![CDATA[<p><a href="https://github.com/">GitHub</a> is a great place to host open-source projects and expose them to a wide community of developers, so it's not surprising that more and more Perl modules are making it their home.</p>

<p>One of the features of GitHub is that it checks if a repository has a <code>README</code> file in its root directory, and displays it on the home page of the repository. This makes the <code>README</code> file a good place to introduce your project to the public.</p>

<p>GitHub also understands a number of markup languages, such as <a href="http://daringfireball.net/projects/markdown/">Markdown</a> and <a href="http://www.textism.com/tools/textile/">Textile</a>, and if the <code>README</code> file is in one of these formats, it will be transformed into nicely formatted HTML. One of the supported formats is <a href="http://perldoc.perl.org/perlpod.html">POD</a>, which means that the standard documentation of a Perl module can be used as its <code>README</code> file and serve as the repository's home page (much like on <a href="http://www.cpan.org/">CPAN</a>).</p>

<p><a href="http://search.cpan.org/dist/Module-Starter/">Module::Starter</a>, which is <a href="http://perldoc.perl.org/perlnewmod.html#Step-by-step:-Making-the-module">Perl's recommended tool for building modules</a>, does not create a GitHub-friendly <code>README</code> file -- instead, the README that it produces contains installation instructions (the <code>"perl Makefile.PL; make..."</code> mantra) and a couple links to module resources. This means that if you want to have a GitHub-friendly <code>README</code> file in your module, you need to either create it yourself, or tweak your build script a bit to have it generate it for you automatically.</p>

<p>This article wouldn't be particularly interesting if I told you to now go and make the <code>README</code> file yourself, would it? So let me show you how to do this automatically with <a href="http://search.cpan.org/perldoc?ExtUtils::MakeMaker">ExtUtils::MakeMaker</a> and <a href="http://search.cpan.org/perldoc?Module::Build">Module::Build</a> based modules (generated with Module::Starter). I will demonstrate how to create two <code>README</code> files: one being the POD version (named <code>README.pod</code>), the other one plain text (named just <code>README</code>).</p>

<h3>ExtUtils::MakeMaker</h3>

<p>Since ExtUtils::MakeMaker creates a <code>Makefile</code> with shell commands, you can tell it to generate the README files using two core Perl command-line utilities: <a href="http://perldoc.perl.org/perldoc.html">perldoc</a> (to generate POD from module's source) and <a href="http://perldoc.perl.org/pod2text.html">pod2text</a> (to convert POD into plain text). Extend <code>Makefile.PL</code> by adding the shell commands as the <code>PREOP</code> attribute of the dist target configuration:</p>

<pre>my $preop =
    'perldoc -uT $(VERSION_FROM) | tee $(DISTVNAME)/README.pod &gt; README.pod;' .
    'pod2text README.pod | tee $(DISTVNAME)/README &gt; README';

WriteMakefile(
    NAME                =&gt; 'Foo::Bar',
    AUTHOR              =&gt; q{Michal Wojciechowski &lt;odyniec@cpan.org&gt;},
    VERSION_FROM        =&gt; 'lib/Foo/Bar.pm',
    ABSTRACT_FROM       =&gt; 'lib/Foo/Bar.pm',
    ($ExtUtils::MakeMaker::VERSION &gt;= 6.3002
      ? ('LICENSE'=&gt; 'perl')
      : ()),
    PL_FILES            =&gt; {},
    PREREQ_PM =&gt; {
        'Test::More' =&gt; 0,
    },
    dist                =&gt; {
        COMPRESS =&gt; 'gzip -9f',
        SUFFIX =&gt; 'gz',
        PREOP =&gt; $preop,
    },
    clean               =&gt; { FILES =&gt; 'Foo-Bar-*' },
);</pre>

<p>Now, when you run <code>perl Makefile.PL</code> and <code>make dist</code>, the two <code>README</code> files will be created for you.</p>

<p>Don't worry if running <code>make dist</code> produces warnings that <code>README</code> and <code>README.pod</code> are missing -- it's no big deal, as the warnings will only be seen by you when making a distribution package, and not by the user building the module.</p>

<h3>Module::Build</h3>

<p>Module::Build defines a <code>docs</code> action, and it's the appropriate place for the code that builds the <code>README</code> files. Two modules that you can use for this purpose are <a href="http://search.cpan.org/perldoc?Pod%3A%3ASelect">Pod::Select</a> and <a href="http://search.cpan.org/perldoc?Pod%3A%3AReadme">Pod::Readme</a>. In your <code>Build.PL</code> file, create a subclass of Module::Build, and define a subroutine named <code>ACTION_docs</code>, similar to the one shown below:</p>

<pre>my $class = Module::Build-&gt;subclass(
    class =&gt; 'My::Builder',
    code =&gt; q{
        sub ACTION_docs {
            use Pod::Readme;
            use Pod::Select;

            my $self = shift;

            podselect({ -output =&gt; 'README.pod' },
                'lib/Foo/Bar.pm');

            my $parser = Pod::Readme-&gt;new();
            $parser-&gt;parse_from_file('README.pod', 'README');

            return $self-&gt;SUPER::ACTION_docs;
        }
    }
);

my $builder = $class-&gt;new(
    module_name         =&gt; 'Foo::Bar',
    license             =&gt; 'perl',
    dist_author         =&gt; q{Michal Wojciechowski &lt;odyniec@cpan.org&gt;},
    dist_version_from   =&gt; 'lib/Foo/Bar.pm',
    requires =&gt; {
        ...
    },
    configure_requires =&gt; {
        'Pod::Readme' =&gt; 0,
        'Pod::Select' =&gt; 0,
    },
    build_requires =&gt; {
        'Pod::Readme' =&gt; 0,
        'Pod::Select' =&gt; 0,
        'Test::More' =&gt; 0,
    },
    add_to_cleanup      =&gt; [ 'Foo-Bar-*' ],
    create_makefile_pl =&gt; 'traditional',
);

$builder-&gt;create_build_script();</pre>

<p>You can now run <code>perl Build.PL</code>, and then <code>./Build docs</code>, to build the <code>README</code> files.</p>

<p>Remember to add the Pod::Select and Pod::Readme modules to <code>configure_requires</code> and <code>build_requires</code>, as shown in the above example.</p>

<h3>Installation instructions</h3>

<p>Since these methods overwrite the original README file provided by Module::Starter, the installation instructions in it are also lost. It's a good practice to always include installation instructions, so go ahead and add an INSTALL file to your module's distribution files. It can be really simple and straight to the point:</p>

<pre>Foo-Bar

INSTALLATION

To install this module, run the following commands:

    perl Build.PL
    ./Build
    ./Build test
    ./Build install</pre>

<p>Finally, remember to add <code>README.pod</code> and <code>INSTALL</code> to your module's <code>MANIFEST</code>.</p>]]>
        
    </content>
</entry>

</feed>
