Peter Staab
Peter Staab

Reputation: 552

How can I share session data between Dancer2 apps with different serializers?

I am trying to migrate an app from Dancer to Dancer2. My thought is to separate the code into routes that are served with templates and those that are Ajax (API) calls.

My base app is:

use strict;
use warnings;
use FindBin; 
use Plack::Builder;

use Routes::Templates;
use Routes::Login; 

builder {
    mount '/'    => Routes::Templates->to_app;
    mount '/api' => Routes::Login->to_app;
};

I was thinking that the Routes::Templates package would not have any serializer and the Routes::Login package would have JSON serialization. I used

set serializer => 'JSON';

in the Routes::Login package.

However, I also want these to share session data so each has a common appname

use Dancer2 appname => 'myapp';

in each file. And that appears to run into trouble with the serialization. The Routes::Template routes are not returning correctly because it is trying to be encoded as JSON. Here's the error:

Failed to serialize content: hash- or arrayref expected (not a simple scalar, use allow_nonref to allow this)

I've read all the documentation, including these:

But I'm still not clear on how the serializer is separated by package.

Upvotes: 1

Views: 471

Answers (1)

ThisSuitIsBlackNot
ThisSuitIsBlackNot

Reputation: 24063

There's no need to combine your apps using appname; session data will be shared as long as both apps use the same configuration for the session engine. (Also, serializers are an all-or-nothing prospect in Dancer2, so you really have to use two separate apps.)

Here's the example I gave on the dancer-users mailing list:

MyApp/lib/MyApp.pm

package MyApp;
use Dancer2;

our $VERSION = '0.1';

get '/' => sub {
    session foo => 'bar';
    template 'index';
};

true;

MyApp/lib/MyApp/API.pm

package MyApp::API;
use Dancer2;

set serializer => 'JSON';

get '/' => sub {
    my $foo = session('foo') // 'fail';
    return { foo => $foo };
};

true;

MyApp/bin/app.psgi

#!/usr/bin/env perl

use strict;
use warnings;
use FindBin;
use lib "$FindBin::Bin/../lib";

use MyApp;
use MyApp::API;
use Plack::Builder;

builder {
    mount '/'    => MyApp->to_app;
    mount '/api' => MyApp::API->to_app;
};

If you access the / route followed by the /api route in the same browser, you'll get

{"foo":"bar"}

indicating that the same session variable was used by both requests.

Upvotes: 0

Related Questions