PerlDancer / Dancer2

Perl Dancer Next Generation (rewrite of Perl Dancer)
http://perldancer.org/
Other
542 stars 274 forks source link

Conflict between apps when using DSL object in plugins #1630

Open nfg opened 3 years ago

nfg commented 3 years ago

Hello!

At $WORK we have a fairly complicated Dancer2 app that's grown over the years. It's composed of three different Dancer2 apps, one handling web requests, another handling API requests, and another for a weird edge case that isn't worth getting into. On development, our psgi file looks something like

builder {
    mount '/' => App::Web->to_app;
    mount '/api' => App::API->to_app;
    mount '/other' => App::Other->to_app;
};

Cool. We have some Dancer2::Plugin cases to share code between them. It's been working pretty well so far.

For a new ticket, we're adding a new endpoint in App::API that uses a plugin, and this plugin -- which worked fine before -- spits out errors like this:

Can't call method \"var\" on an undefined value at lib/App/Plugin/StaticPage.pm line 273.\n

And the line is

$plugin->dsl->app->request->var('layout' => $page->layout);

OK. I dug into it. Eventually I figured out that for that bit of code, $plugin->app and $plugin->dsl->app referred to the different apps. I need to render a template in the API with $plugin->dsl->template. Calling that invokes the hooks for the web app, and from there everything blows up. It looks like whichever app loads the plugin first stakes its claim on the dsl() function installed by Dancer2::Plugin:

https://github.com/PerlDancer/Dancer2/blob/92ed2f64a9b814fc4f0f2c06c9123d4cf49cbaf4/lib/Dancer2/Plugin.pm#L474-L483

In short: I think multiple instances of the same plugin share the same dsl object. This causes weird conflicts between the apps.

I'll see if I can put together a merge request reproducing this behaviour.