Search code examples
perldancer

Multiple app directories with Dancer perl


Is there a way to have one app in dancer but with multiple appdirs.

Or could I do something like this:

My project is in dir 'foo'. And let's say that I have a dir 'bar' (not inside 'foo') which has a directory called 'public'. I what my app 'foo' to use this public as its own public and if it searches for let's say '/css/style.css' and it is not in '/bar/public/' it should search the '/foo/public/'. How can I do that?


Solution

  • One of the ways if to write a plugin that renders static (and replaces some functionality). You can use Dancer::Plugin::Thumbnail as an example.

    Other way I see is to monkey-patch get_file_response() at Dancer::Renderer which is not really such a good idea.

    Following code looks for static files in each dir from @dirs array. It's dirty, ugly and unsafe. This can be broken in future version and may cause problems with other parts of Dancer framework I'm not familiar with. You're warned.

    #!/usr/bin/env perl
    use Dancer;
    use Dancer::Renderer;
    use MyWeb::App;
    
    my $get_file_response_original = \&Dancer::Renderer::get_file_response;
    my @dirs = ('foo');
    
    *Dancer::Renderer::get_file_response = sub {
        my $app = Dancer::App->current;
    
        my $result;
    
        # Try to find static in default dir
        if ($result = $get_file_response_original->(@_)) {
            return $result;
        }
    
        # Save current settings
        my $path_backup = $app->setting('public');
    
        # Go through additional dirs
        foreach my $dir (@dirs) {
            $app->setting(public => $dir);
            if ($result = $get_file_response_original->(@_)) {
                last;
            }
        }
    
        # Restore public
        $app->setting('public' => $path_backup);
    
        return $result
    };
    
    dance;
    

    Third ways is to let nginx just do this work for you by writing proper nginx config for your application.