Django Day 2012, Brescia

In uno slancio del tutto estemporaneo di apostasia, il 21 Aprile sono andato al Django Day 2012. In realtà, pur programmando in Perl ed utilizzando framework come Catalyst e Mojolicious, sono sempre stato curioso nei confronti di Django, che ho esplorato poco ma che mi è parso un progetto interessante.

La conferenza, tenutasi a Brescia, è stata organizzata dagli ottimi WEBdeBS, un gruppo che già aveva dato vita ad altri riusciti eventi come la NodeJS Conf nel 2011. La strepitosa venue va ricordata in particolar modo per il soffitto affrescato della sala.

Globalmente gli interventi sono stati di buon livello, spaziando da database noSQL a bioinformatica... molto interessante il talk di Roberto de Ioris sui server di produzione, valido anche al di fuori del mondo Django. Oltre ad interventi inerenti all'utilizzo di Django, ne è stato presentato anche uno per chi vuole contribuire allo sviluppo del framework (proponendo feature, patch, ...). 20 Euro spesi alla grande per la qualità dell'evento!

Django Day 2012, Brescia

C'erano bottiglie d'acqua sempre disponibili per tutti, e nei coffee break in giardino non mancavano gustosi pasticcini e succo di frutta in abbondanza. Ho un piccolo rimpianto per non essere riuscito ad acquistare una maglietta prima che si esaurissero: da un lato è stata colpa mia (non l'avevo prenotata), dall'altro forse è meglio così poiché ho il cassetto delle t-shirt che già esplode...

A pranzo ho avuto occasione di scambiare due chiacchiere con alcuni membri della simpatica ciurma dei WEBdeBS, che sono pieni di ottime idee per eventi futuri (Vim Day, ..., date un'occhiata al loro sito). Parlando del pranzo in sé, per 10 Euro ho mangiato il giusto e bevuto una birra media, e c'è stato anche un curioso siparietto con il cameriere che era risentito poiché eravamo in troppi (il locale era praticamente vuoto). :-)

Sono anche riuscito a farmi un'idea su Django un po' più precisa di quella che avevo prima. Mi è parso ottimo come sistema pronto all'uso (include ORM, sistema di templating, ..). D'altra parte mi sembra meno flessibile di quanto avevo immaginato, in particolare per quanto riguarda l'ORM: tanto per fare un esempio, per utilizzare un database noSQL (MongoDB) è stato necessario forkare Django (!). Capisco che si tratta di scelte specifiche, è sempre necessario un compromesso tra la comodità d'uso e la flessibilità del sistema.

E ho scoperto che anche per Python esiste un'equivalente di perlbrew... si chiama - che sorpresa :-) - pythonbrew.

In definitiva, una bella giornata ed un interessante evento. Complimenti ai WEBdeBS!

I coded a simple JSON web service, which converts any HTML input to PDF (using the excellent wkthmltopdf software). You can supply HTML code or an URI where to get it.

Using the powerful Mojolicious web framework (Mojolicious::Lite is enough for this application, actually) framework it's just roughly 100 lines of code for the whole thing:

#!/usr/bin/perl

# Pulls in strict and unicode_strings, but this
# program doesn't require perl 5.14 to work
use v5.14;

use Mojolicious::Lite;
use Path::Class;
use File::Temp;
use Mojo::UserAgent;
use MIME::Base64;

my $config = {
    wkh     => '/usr/local/bin/wkhtmltopdf',
    tmpdir  => '/tmp',
    auth    => 'maitai',
};

post '/' => sub {
    my $self = shift;
    
    my $args = $self->req->json;

    # Handle obvious error cases
    return $self->mkerror('invalid-JSON-content')
        if !defined $args;
    return $self->mkerror('invalid-auth-information')
        if $args->{auth} ne $config->{auth};
        
    # Clients can pass us HTML content or an URI where to fetch if
    if ( !defined $args->{html} ) {
        return $self->mkerror('no-html-nor-uri')
            if !$args->{uri};
        
        # Fetch the page
        my $ua = Mojo::UserAgent->new();
        my $tx = $ua->get($args->{uri});
        my $res = $tx->success;
        if (!$res) {
            my ($msg, $code) = $tx->error;
            return $self->mkerror("fetch-page-error: $msg");
        }
        $args->{html} = $res->body;
    }

    my $html_file = $self->make_html_file( $args->{html} );

    my $pdf_fn = $html_file->filename;
    $pdf_fn =~ s/\.html/.pdf/xms;

    # Build the command line
    my $hcmd = $self->build_wkh_command($args);
    $hcmd .= ' ' . $html_file->filename . " $pdf_fn";

    # Create the PDF file
    my $output = `$hcmd`; # TODO: error handling

    # Read the output and return it
    my $pdf_file = Path::Class::File->new($pdf_fn);
    my $pdf = $pdf_file->slurp();

    # Unlink the PDF file
    $pdf_file->remove();

    return $self->render_json({
        status  => 'ok',
        pdf     => encode_base64($pdf),
    });
};

helper build_wkh_command => sub {
    my ($self, $args) = @_;

    # Usual page size A4, but labels would need a smaller one so we leave it
    my $page_size = '--page-size ' . ($args->{page_size} || 'a4');

    # Custom page size will override the previous
    if ( defined $args->{page_width} && defined $args->{page_height} ) {
        $page_size = "--page-width $args->{page_width}"
            . " --page-height $args->{page_height} ";
    }

    # Build htmldoc command line
    my $hcmd = $config->{wkh} ." --encoding \"utf-8\" $page_size ";
    $hcmd .= "--margin-top $args->{top_margin}mm "
        if defined $args->{top_margin};
    $hcmd .= "--margin-left $args->{left_margin}mm "
        if defined $args->{left_margin};
    $hcmd .= "--margin-bottom $args->{bottom_margin}mm "
        if defined $args->{bottom_margin};
    $hcmd .= "--margin-right $args->{right_margin}mm "
        if defined $args->{right_margin};
    $hcmd .= "--orientation $args->{orientation} "
        if defined $args->{orientation};

    return $hcmd;
};

helper make_html_file => sub {
    my ($self, $html) = @_;

    my $htmlf = File::Temp->new(
        DIR     => $config->{tmpdir},
        SUFFIX  => '.html',
        UNLINK  => 1,
    );
    binmode $htmlf, ':encoding(UTF-8)';
    print $htmlf $html;

    return $htmlf; 
};

helper mkerror => sub {
    my ($self, $error) = @_;
    
    return $self->render_json({
        status  => 'error',
        error   => $error,
    });
};

app->start;

Once you have this setup (via CGI, FastCGI, morbo, starman or whatever you like best), you just need to POST you data via JSON, and it could be something like:

{
    "auth"    : "maitai",
    "html"    : "<html><head><meta charset=UTF-8></head><body>Ciao!</body></html>"
}

or:

{
    "auth"    : "maitai",
    "uri"     : "http://www.skm.to/"
}

and you get a JSON response such as this:

{
    "status"  : "ok",
    "pdf"     : "pdf_data_base64_encoded"
}

The PDF data is base64 encoded in order to be safely transferred without risking corruption because of character set encoding/decoding.

Some notes:

  • There are some configuration options (page size, ...): take a look at the source code.
  • Not all wkhtmltopdf features are implemented, but it's very easy to extend the software.
  • Authentication system is just an example, it should be way more robust.
  • Arguments should really be checked for safety, otherwise security issues could arise (well, provided the authentication system is broken before).
  • Error handling should be improved.

Why did I do this? Basically, I have some web apps hosted under a managed FreeBSD server, where compiling wkhtmltopdf does not work very well (and there are a lot of pre-requisites, anyway). This way I can "outsource" PDF generation easily.

Nasce Udine Programmers

| | Comments (0)

È nato Udine Programmers, un'idea che si propone di diventare un punto d'incontro per i programmatori (e le figure "collegate" come sistemisti, web designer, ...) di Udine e del Friuli.

Questo è l'attuale breve manifesto:

Studi o lavori su qualcosa che ha a che fare con la programmazione?
Vuoi conoscere altri programmatori?
Hai un progetto e cerchi collaboratori?
Cerchi lavoro come programmatore?
Ti servono consigli relativi alla programmazione?

Sull'esempio del Programmers in Padua, l'idea è quella di creare un punto di incontro per persone che si occupino di programmazione e attività correlate, in Friuli.

Tra gli scopi dell'iniziativa: permettere a persone che fan lavori simili di conoscersi (e quindi anche di scambiarsi possibilità di lavoro), organizzare meeting tecnici, cenare qualche volta assieme.

Professionisti, appassionati, studenti sono i benvenuti, come chiunque altro!

Ti aspettiamo!!!

http://www.udineprogrammers.it/

Beh... eccomi qua con qualche riga sull'Open Source Day 2011. Nel globale, gran manifestazione - con 3 tracce contemporanee ed una partecipazione direi abbondante di persone. Purtroppo ho seguito poco del convegno, poiché gestivo il tavolo dell'associazione Perl.It. Ho però dato un'occhiata qua e la e non sembravano mancare talk interessanti. Molto appropriata l'idea degli speed talk: uno spazio in corridoio dove chiunque poteva cimentarsi parlando in breve di qualcosa - ideale per chi vuol fare un intervento breve oppure non è abituato a parlare di fronte ad una platea e magari vuole iniziare in maniera più "morbida".

C'era l'immancabile Install Fest, dove in pratica uno porta il proprio PC su cui vuole installare Linux o un altro sistema operativo open source e può ottenere assistenza nell'installazione ed informazioni sull'utilizzo del sistema. L'Install Fest è sempre una parte importante ed utile in queste manifestazioni. Il Game Corner sembrava particolarmente interessante, nel senso che tutti si divertivano. Purtroppo durante il giorno non ho avuto granché tempo di cimentarmi e verso sera ormai era tardi per battersi in maniera competitiva con chi ormai aveva preso confidenza dalla mattina con le sparatorie - quindi mi sono limitato a dare un'occhiata.

Una bella iniziativa, che non ho visto in altre conferenze di questo tipo, era l'Area Bimbi. Il nome parla da sé: mentre segui le conferenze puoi lasciare i pargoletti nelle mani dell'eccellente staff dell'Open Source Day, che provvederà a fargli passare il tempo divertendosi. Fantastica idea!

Il pranzo self-service costava appena 10 Euro (OK, non ho pagato in quanto speaker in realtà) ed era piuttosto buono ed abbondante. Anche il bar interno all'Università era sempre aperto e a disposizione dei partecipanti.

Per quanto ho potuto vedere l'evento è filato via liscio come l'olio, e lo staff della reception - sempre molto disponibile - ha svolto un ottimo lavoro nel fornire supporto ai partecipanti (mi ci sono rivolto 2-3 volte, e per questioni non banali).

L'unico (piccolissimo) appunto che faccio per una manifestazione comunque riuscita alla grande è relativo alla mancanza di un evento serale: sarebbe bello ci fosse una cena "sociale" programmata (a cui uno si pre-iscrive, oppure paga il giorno stesso se ci sono ancora posti), sono sicuro non mancherebbero spunti per varie discussioni tecniche e non, per fare amicizia, e (perché no) per tirare tardi in giro per Udine.

Presentazion 0.60 is out, with some changes and many important bugfixes and optimizations.

Here's the change log:

Version 0.60 - 2011-11-18
    - Calculation of font size is now much more precise
    - Padding settings now moved to CSS file, so they can be
        * customized without changing the JS file
        * be different from screen to PDF/print version
    - Fixed ULs and OLs so list markers are inside the div and
      there's no risk of them crossing boundaries
    - Some code refactoring/optimization
    - Allow comments in multislides (lines beginning with //
      are ignored). Took the idea from a fork by stevan, but
      implemented it differently.
    - Fixed a bug which didn't allow to have multiple
      multislides in one presentation (thanks stevan)

See the original blog post for download and other information.

Find recent content on the main index or look in the archives to find all content.

Recent Assets

  • thunderbird_logo.png

Categories

Pages

Powered by Movable Type 4.23-en