Search code examples
perldancerplackpsgi

Multilingual PSGI-web deployment


I plan develop one web application with PSGI/Plack. (probaly with Dancer, but not decided yet).

The applicatiion should be utf8, multilingual (with Locale::Maketext) and (ofc) will contain some statical pages in the given language. My idea is deploy it in different language domains like en.example.com, de.example.com etc. The application itself is simple, mostly will only fill templates with localized texts and some other (light) functionality.

What is the best solution to deploying one application for mutiple language-based sub-domains in one physical machine?

My current research ended with this solution: need to use Apache and its name based virtual servers for every language subdomain.

<VirtualHost en.example.com>
    ServerName en.example.com
    DocumentRoot /path/to/site/en/files
    <Location />
        SetHandler perl-script
        PerlResponseHandler Plack::Handler::Apache2
        PerlSetVar psgi_app /path/to/site/en/en.psgi
    </Location>
</VirtualHost>

Questions:

  • What is the best solution?
  • Exists any solution with Starman or other pure-perl server? If yes, how? Reverse proxy?
  • Will be the pure perl solution better (faster)?
  • should i consider some other solution? (fcgi, nginx etc...)

Any other ideas/things what can have impact to development itself?


Solution

  • Use Plack::App::URLMap to setup a virtualhost in Starman (or whatever PSGI compatible web servers):

    use Plack::App::URLMap;
    my $en_app = generate_app('en');
    my $ru_app = generate_app('ru');
    
    my $app = Plack::App::URLMap->new;
    $app->map("http://en.example.com/" => $en_app);
    $app->map("http://ru.example.com/" => $ru_app);
    $app->to_app;
    

    in generate_app you can setup/configure whatever needed to return a new PSGI app. If you want to share the same $app instance but want to dynamically change the behavior, you can do so by writing PSGI middleware, like:

    my $app = sub { MyApp->run(@_) };
    my $en_app = sub {
       my $env = shift;
       $env->{'myapp.language'} = 'en';
       $app->($env);
    };
    my $ru_app = sub { ... }; # same
    

    Note that you probably want to put Starman behind proxy, in which case you should configure the frontend (nginx/Apache/lighttpd etc.) to forward the Host: header as it is to the backend.