2011-09-07 24 views
5

有沒有辦法讓一個應用程序在舞者,但與多個appdirs。多個應用程序目錄與舞者perl

或者我可以做這樣的事情:

我的項目是在目錄「富」。假設我有一個dir'bar'(不在'foo'裏面),它有一個名爲'public'的目錄。我的應用'foo'使用這個公衆作爲它自己的公共,如果它搜索'/css/style.css'而它不在'/ bar/public /'中,它應該搜索'/ foo /上市/'。我怎樣才能做到這一點?

回答

2

如何編寫呈現靜態(並替換某些功能)的插件的方式之一。您可以使用Dancer::Plugin::Thumbnail作爲示例。

我看到的其他方式是猴子補丁get_file_response()Dancer::Renderer這不是一個真正的好主意。

以下代碼在@dirs數組的每個目錄中查找靜態文件。它很髒,醜陋和不安全。 這可能會在將來的版本中被打破,並可能導致我不熟悉的Dancer框架的其他部分出現問題。你被警告。

#!/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; 

第三個方法就是讓nginx的只是這樣做對你的工作通過寫適當的nginx的配置爲您的應用。

+0

的想法是,這兩個目錄應保持分離。 – bliof

+0

@bliof我更新了我的答案,您可以試試這個,但最好使用nginx。 – yko

+0

我在想別的東西。我可以製作'foo'插件並在'bar'中使用它嗎?實際的問題是舞者插件是否具有舞者應用程序的功能。我的意思是我可以從它映射URL並從它的'views'文件夾中加載模板? /我從來沒有寫過一個插件/ – bliof

7

好的,這是做這件事的好方法。它當然可以是一個插件。

你永遠不應該通過舞者的核心內部黑客做這樣的事情,你倒是應該總是考慮實施一個路由處理程序來完成這項工作:

#!/usr/bin/env perl 
use Dancer; 
use File::Spec; 
use Dancer::FileUtils 'read_file_content'; 
use Dancer::MIME; 
use HTTP::Date; 

# your routes here 

# then the catchall route for 
# serving static files 

# better in config 
my @public_dirs = qw(/tmp/test/foo /tmp/test/bar /tmp/test/baz); 

get '/**' => sub { 
    my $path = request->path; 
    my $mime = Dancer::MIME->instance; 

    # security checks 
    return send_error("unauthrorized request", 403) if $path =~ /\0/; 
    return send_error("unauthrorized request", 403) if $path =~ /\.\./; 

    # decompose the path_info into a file path 
    my @path = split '/', $path; 

    for my $location (@public_dirs) { 
     my $file_path = File::Spec->catfile($location, @path); 

     next if ! -f $file_path; 

     my $content = read_file_content($file_path); 
     my $content_type = $mime->for_file($file_path); 
     my @stat = stat $file_path; 

     header 'Content-Type', $content_type; 
     header 'Content-Length', $stat[7]; 
     header 'Last-Modified', HTTP::Date::time2str($stat[9]); 
     return $content; 
    } 

    pass; 
}; 

start; 

這個應用程序運行的一個例子:

$ mkdir -p /tmp/test/foo /tmp/test/bar /tmp/test/baz 
$ echo 1 > /tmp/test/foo/foo.txt 
$ echo 2 > /tmp/test/bar/bar.txt 
$ echo 3 > /tmp/test/baz/baz.txt 
$ ./bin/app.pl 
$ curl -I http://0:3000/baz.txt 
HTTP/1.0 200 OK 
Content-Length: 2 
Content-Type: text/plain 
Last-Modified: Fri, 14 Oct 2011 11:28:03 GMT 
X-Powered-By: Perl Dancer 1.3051