Sawyer X on blogs.perl.org recently wondered how one could run a Dancer application under a 100% CGI environment.
Indeed, he came up quickly with a REST app in development stage and wanted to go on air with a plain old CGI script. He seems to think it’s not possible with Dancer but as Dancer supports PSGI/Plack, he’s wrong ;)
Thanks to the PSGI/Plack goodness, any application can be powered by a Plack-supported server. CGI is one of them and is implemented by Plack::Server::CGI.
By taking a quick look at the POD, we see that all we have to do is to write a pretty simple CGI script to bridge the Dancer app with Apache:
#!/usr/bin/perl use Plack::Server::CGI; use Plack::Util; my $psgi = '/path/to/your/app/app.psgi'; my $app = Plack::Util::load_psgi($psgi); Plack::Server::CGI->new->run($app);
We now have to tell Apache that everything should be dispatched to that very CGI script like the following:
<VirtualHost ....>
<Directory "/path/to/your/app">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
AddHandler cgi-script .cgi
</Directory>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /dancer.cgi [QSA,L]
[...]
</VirtualHost>
And… we’re done! Every request the Apache server catches is now served by Dancer through Plack::Server::CGI
All I have to say here is … Plack++ (or @miyagawa++ which seems to be the same ;-)
Can you post an example using rewriterules instead of an AddHandler config? I have hacked together a CGI+mod_rewrite solution (no access to virtualhost config), but I suspect it’s doing more work than it needs to.
I followed your instruction on: http://www.sukria.net/fr/archives/2009/09/20/mounting-a-dancer-app-into-apache-psgiplack/
But got a compilation warning with the following stack error:
main in /home/saturn/perl5/bin/plackup l. 9
Plack::Runner in /home/saturn/perl5/lib/perl5/Plack/Runner.pm l. 120
Plack::Server::Standalone in /home/saturn/perl5/lib/perl5/Plack/Server/Standalone.pm l. 51
Plack::Server::Standalone in /home/saturn/perl5/lib/perl5/Plack/Server/Standalone.pm l. 101
Plack::Server::Standalone in /home/saturn/perl5/lib/perl5/Plack/Server/Standalone.pm l. 142
Plack::Util in /home/saturn/perl5/lib/perl5/Plack/Util.pm l. 127
Try::Tiny in /home/saturn/perl5/lib/perl5/Try/Tiny.pm l. 39
Try::Tiny in /home/saturn/perl5/lib/perl5/Try/Tiny.pm l. 42
Plack::Util in /home/saturn/perl5/lib/perl5/Plack/Util.pm l. 121
Plack::Component in /home/saturn/perl5/lib/perl5/Plack/Component.pm l. 39
Plack::Middleware::ContentLength in /home/saturn/perl5/lib/perl5/Plack/Middleware/ContentLength.pm l. 10
Plack::Component in /home/saturn/perl5/lib/perl5/Plack/Component.pm l. 39
Plack::Middleware::AccessLog in /home/saturn/perl5/lib/perl5/Plack/Middleware/AccessLog.pm l. 21
Plack::Component in /home/saturn/perl5/lib/perl5/Plack/Component.pm l. 39
Plack::Middleware::StackTrace in /home/saturn/perl5/lib/perl5/Plack/Middleware/StackTrace.pm l. 27
Try::Tiny in /home/saturn/perl5/lib/perl5/Try/Tiny.pm l. 39
Try::Tiny in /home/saturn/perl5/lib/perl5/Try/Tiny.pm l. 42
Plack::Middleware::StackTrace in /home/saturn/perl5/lib/perl5/Plack/Middleware/StackTrace.pm l. 27
Plack::Util in app.psgi l. 12
Dancer in /home/saturn/perl5/lib/perl5/Dancer.pm l. 131
Dancer::Handler::PSGI in /home/saturn/perl5/lib/perl5/Dancer/Handler/PSGI.pm l. 21
Dancer::Handler in /home/saturn/perl5/lib/perl5/Dancer/Handler.pm l. 60
Dancer::Renderer in /home/saturn/perl5/lib/perl5/Dancer/Renderer.pm l. 24
Dancer::Renderer in /home/saturn/perl5/lib/perl5/Dancer/Renderer.pm l. 96
Dancer::Route in /home/saturn/perl5/lib/perl5/Dancer/Route.pm l. 235
Dancer::Error in /home/saturn/perl5/lib/perl5/Dancer/Error.pm l. 21
Dancer::Error in /home/saturn/perl5/lib/perl5/Dancer/Error.pm l. 120
What could be causing the problem?
Currently, plackup use warn to tell the user the connection is up, and Dancer will catch that warning as a “Compilation Warning”. That’s either a strictness leak in Dancer’s code or an overuse of warn in plackup, depending on the point of view of the observer.
Anyways, I’m going soon to fix that in Dancer’s code, and hopefully plackup won’t use warn to output information on STDERR.
In the meantime, I suggest you just disable the strict mode in Dancer by setting watnings to false, in your config.yml file:
warnings: 0
Hey!
Yesterday, a few hours after my post, I was sitting at a hummus place with my girlfriend. I told her about the post I wrote. I decided to take a minute to check online if anyone has any example of how to run PSGI as CGI.
One of the first results on Google was this page!
So, first of all, thanks for taking the time to correct me and show me an actual example of how to do this.
Secondly, thanks for Dancer! :)
@trydancing: issue reported: http://github.com/sukria/Dancer/issues#issue/14 and BTW, miyagawa has fixed the warn in Plack::Server::Standalone so both sides will be fixed soon.
@Sawyer X : you’re welcome, thanks for blogging about Dancer, that’s really nice!
Thanks for the prompt response.
sukria++, miyagawa++
I disabled warning to play around with Dancer and was able to create a simple yet working website in only hours.
Dancer rocks!
And now that miyagawa shiped CGI::PSGI 0.07, we can deploy any Dancer app under Apache2 + mod_perl as well.
You are aware that you can run any .psgi as CGI by setting the shebang to use plackup and making the .psgi executable?
Like this: #!/usr/bin/env plackup
This of course requires that plackup is available in the path of the user running CGI script. If you use local::lib or PERL5LIB things quickly get more complicated. If you’re into running it as fastcgi (for more speed) without having root you should take a look at my Plack::App::Apache::ActionWrapper on CPAN.
Yes, Robin’s example is more compatible an DRY (Do not Repeat Yourself) since that works as a FCGI script as well as a standalone server.
Alternatively you can write like:
use Plack::Runner;
Plack::Runner->run(‘/path/to/your/app.psgi’);
We’re in the process of renaming Plack::Server into something else now, and i recommend you to write your bootstrap script like that.