2011-10-22 65 views
1

我们在亚马逊S3上存储大量文件,我们希望网站访问者能够通过AJAX访问,但我们不希望向访问者透露实际的文件位置。简单的Perl代理

为了达到这个目的,我希望做的是向一个非常简单的perl脚本发出一个AJAX请求,该脚本只是作为代理并将文件返回给浏览器。我已经有脚本设置来验证用户是否登录并执行数据库查询以找出正确的URL来访问S3上的文件,但我不确定将文件返回到Vistor浏览器的最佳方式最有效的方式。

任何建议,最好的方式来完成这将不胜感激。谢谢!

+0

如果您想阻止他们看到该位置,您必须从脚本中打开文件并将其回显给用户的浏览器。您可以使用标题使它看起来像他们正在下载原始文件。 –

+0

@SamDufel - 谢谢。我应该使用任何示例代码或建议模块来最大限度地减少最终用户的加载时间? –

+0

对不起,我主要使用php,而不是perl。我可以给你一个例子在PHP中,但我不知道这将是多么有用...... –

回答

1

好的。有一个例子是如何使用Mojolicious框架来实现的。 我想你运行这个脚本作为守护进程。脚本捕获到/json_dir/.*的所有请求,将此请求发送到Stackoverflow API并返回响应。 您可以运行该脚本./example.pl daemon,然后尝试http://127.0.0.1:3000/json_dir/perl

对此你应该能够找到你的标题为“简单的Perl代理”自己的问题。 这段代码可以作为监听特定端口和CGI脚本的独立守护进程使用(首选)。

#!/usr/bin/env perl 
use Mojolicious::Lite; 

get '/json_dir/(.filename)' => sub { 
    my $self = shift; 

    my $filename = $self->stash('filename'); 
    my $url = "http://api.stackoverflow.com/1.1/questions?tagged=" . $filename; 

    $self->ua->get(
     $url => sub { 
      my ($client, $tx) = @_; 
      json_response($self, $tx); 
     } 
    ); 

    $self->render_later; 
}; 

sub json_response { 
    my ($self, $tx) = @_; 
    if (my $res = $tx->success) { 
     $self->tx->res($res); 
    } 
    else { 
     $self->render_not_found; 
    } 
    $self->rendered; 
} 

app->start; 

__DATA__ 

@@ not_found.html.ep 
<!doctype html><html> 
    <head><title>Not Found</title></head> 
    <body>File not found</body> 
</html> 
2

最好的方法是使用sendfile system call。如果您打开并手动从磁盘读取文件,然后再将它按块方式写入Web框架的“接收器”端,那么您非常浪费,因为数据必须通过RAM传送,可能包括缓冲。

你在你的问题中描述的是一种非常常见的模式,因此许多解决方案已经存在围绕设置special HTTP header的想法,然后让应用程序下面的Web堆栈有效地处理它。

采用XSendfile中间件在普拉克设置合适的报头。下面的最小程序将DTRT并在可能的情况下利用系统调用。

use IO::File::WithPath qw(); 
use Plack::Builder qw(builder enable); 
builder { 
    enable 'Plack::Middleware::XSendfile'; 
    sub { 
     return [200, [], IO::File::WithPath->new('/usr/src/linux/COPYING')]; 
    } 
};