Archive for December, 2011

Alternative Dancer Templating Engines

Sunday, December 18th, 2011

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’re not happy with the default simple engine or with Template Toolkit, there is now a dozen different alternatives to choose from. Let’s take a look at some of them.

Dancer::Template::Tiny

Template::Tiny 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).

Dancer::Template::Tiny is going to replace Dancer::Template::Simple as the default templating engine in Dancer2.

Example template:

<html>
  <head>
    <title>Tiny Example</title>
    <link rel="stylesheet" href="[% request.uri_base %]/css/style.css" />
  </head>
  <body>
    <h1>Hello, World! This is Dancer [% dancer_version %]!</h1>
    <p>
      [% IF morning %]
        Good morning!
      [% ELSE %]
        Good afternoon!
      [% END %]
    </p>
  </body>
</html>

Route handler:

use DateTime;
   
get '/hello' => sub {
    template 'hello', { morning => (localtime)[2] < 12, now => DateTime->now };
};

Dancer::Template::Tenjin

Tenjin 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 Dancer::Template::Tenjin.

Example template:

<html>
  <head>
    <title>Tenjin Example</title>
    <link rel="stylesheet" href="[== $request->uri_base =]/css/style.css" />
  </head>
  <body>
    <h1>Hello, World! This is Dancer [= $dancer_version =]!</h1>
    <p>
      <?pl if ((localtime)[2] < 12) { ?>
        Good morning!
      <?pl } else { ?>
        Good afternoon!
      <?pl } ?>
    </p>
    <p>
      Current time is: [== DateTime->now->hms =]
    </p>
  </body>
</html>

Route handler:

use DateTime;
   
get '/hello' => sub {
    template 'hello';
};

Dancer::Template::Haml

Haml, 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. Dancer::Template::Haml is a wrapper around Text::Haml and lets you use Haml templates in Dancer applications.

Example template:

%html
  %head
    %title Haml Example
    %link(rel="stylesheet" href="#{$request->uri_base}/css/style.css")
  %body
    %h1 Hello, World! This is Dancer #{$dancer_version}!
    %p
      - if ((localtime)[2] < 12) {
        Good morning!
      - } else {
        Good afternoon!
      - }
    %p Current time is: #{DateTime->now->hms}

Route handler:

use DateTime;
   
get '/hello' => sub {
    template 'hello';
};

More

There are many more interesting templating engines ready to be used with Dancer, such as Mason (provided by Dancer::Template::Mason) or Xslate (Dancer::Template::Xslate). Do a CPAN or MetaCPAN 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!

This post was originally published as part of the 2011 Dancer Advent Calendar.

Serving Files with Dancer::Plugin::DirectoryView and Dancer::Plugin::Auth::Htpasswd

Tuesday, December 13th, 2011

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 mod_autoindex) to allow user access to directories/files on the server, and htpasswd files to password-protect some of those directories.

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: Dancer::Plugin::DirectoryView and Dancer::Plugin::Auth::Htpasswd. Let me now show you how to use them.

Directory Indexes

Let’s say we have a files directory under public, 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:

      package MyWebApp;

      ...

      use Dancer::Plugin::DirectoryView;

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

      plugins:
          DirectoryView:
              url: /pub
              root_dir: files

That’s it — now, if we launch our app and point the browser at the /pub URL, we’ll see the contents of the directory:

Protecting Directories with Htpasswd Files

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

First, let’s create the htpasswd file and an user, named “alice”:

      $ htpasswd -c htpasswd alice

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

(If you’re migrating from Apache and already have the htpasswd file, you just need to copy it to your Dancer application.)

In our Dancer application, we include the Auth::Htpasswd plugin:

      package MyWebApp;

      ...

      use Dancer::Plugin::Auth::Htpasswd;

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

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

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

Let’s see if our protection works. We restart the application and try to access the /pub/secret/ URL:

Great, our confidential files are safe. Only when we log in as “Alice”, we’ll be able to access them:

This post was originally published as part of the 2011 Dancer Advent Calendar.

  • Archives

  • Categories

  • Meta

  • Latest Tweets


    Warning: Illegal string offset 'last_access' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 334

    Warning: Illegal string offset 'time_limit' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 334

    Warning: Illegal string offset 'last_access' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 336

    Warning: Illegal string offset 'twitter_api' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 234

    Warning: Illegal string offset 'user_token' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 262

    Warning: Illegal string offset 'user_secret' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 263

    Warning: Illegal string offset 'consumer_key' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 264

    Warning: Illegal string offset 'consumer_secret' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 265

    Warning: Illegal string offset 'twitter_username' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 270

    Warning: Illegal string offset 'show_retweets' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 272

    Warning: Illegal string offset 'exclude_replies' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 275

    Warning: Illegal string offset 'twitter_data' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 282

    Warning: Illegal string offset 'twitter_data' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 350

    Warning: Illegal string offset 'twitter_data' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 351
    Twitter outputted an error:
    .
    Warning: Illegal string offset 'time_format' in /usr/local/www/odyniec.net/public/blog/wp-content/plugins/twitget/twitget.php on line 484
  • Follow odyniec on Twitter