使用 Dancer perl 的多个应用程序目录

发布于 2024-12-03 03:45:57 字数 231 浏览 0 评论 0 原文

有没有一种方法可以在 dancer 中拥有一个应用程序,但具有多个应用程序目录。

或者我可以这样做:

我的项目位于 dir 'foo' 中。假设我有一个目录“bar”(不在“foo”内),其中有一个名为“public”的目录。我的应用程序“foo”使用这个公共作为自己的公共,如果它搜索“/css/style.css”并且它不在“/bar/public/”中,它应该搜索“/foo/”民众/'。我怎样才能做到这一点?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

戏剧牡丹亭 2024-12-10 03:45:57

好的,这是一个好方法。它当然可以是一个插件。

你永远不应该通过侵入 Dancer 的核心来做这种事情,你应该总是考虑实现一个路由处理程序来完成这项工作:

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

OK, here is the good way to do it. It can of course be a plugin.

You should never do this kind of things by hacking inside Dancer's core, you should rather always consider implementing a route handler to do the job:

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

An example of this app running:

$ 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
七月上 2024-12-10 03:45:57

一种方法是编写一个呈现静态的插件(并替换一些功能)。您可以使用 Dancer::Plugin::Thumbnail 作为示例。

我看到的另一种方法是在 get_file_response() ="nofollow">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 配置来为您完成这项工作。

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.

笨死的猪 2024-12-10 03:45:57

也许这个模块会对您有所帮助?
https://github.com/Perlover/Dancer-Plugin-Hosts
您可以使用自己的 appdir 和 appdir 在 Dancer 中设置虚拟站点。其他目录设置
我今天把这个模块上传到github了
很快就会加入CPAN

May be this module will help to you?
https://github.com/Perlover/Dancer-Plugin-Hosts
You can setup virtual sites in Dancer with own appdir & other directory settings
I uploaded this module today to github
Soon will be in CPAN

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文