2012-06-04 29 views
0

我试图使用HTTP :: Proxy来为某些特定域的服务器403错误。我已经设法修改标题,但代理继续提供原始页面。HTTP :: Proxy:如何替换整个HTML页面

这里是我使用的代码:

package Filters::Filter403; 

use strict; 
use warnings; 
use HTTP::Proxy::HeaderFilter::simple; 
use HTTP::Proxy::BodyFilter::simple; 

our $header = HTTP::Proxy::HeaderFilter::simple->new (
    sub { 
     $_[2]->code(403); 
     $_[2]->message ('Forbidden'); 
    } 
); 

our $body = HTTP::Proxy::BodyFilter::simple->new (
    sub {  
     $_[1] = \<<'HTML'; 
<!DOCTYPE html> 
<html><head><title>403 Forbidden</title><style type="text/css"> 
body { padding: 40pt; } 
body, h1, h2, p { color: #333; font-family: Arial, sans-serif; margin: 0; } 
div { width: 200px; background: #eee; padding: 2em; } 
</style></head><body><div><h1>403</h1><h2>Forbidden</h2></div></body></html> 
HTML 
    } 
); 

1; 

这是从那里我打电话这两个过滤器的主要脚本代码,这样你就可以有一个更美好的期待:

use HTTP::Proxy qw(:log); 
use Getopt::Long; 

use FindBin qw($Bin); 
use lib $Bin; 

use Filters; 
use HTTP::Proxy::BodyFilter::complete; 

my $port = 3128; 
my $fail_at; 
my $outputfile = '/var/log/cvmfs-test/webproxy.output'; 
my $errorfile = '/var/log/cvmfs-test/webproxy.error'; 

my $ret = GetOptions ("port=i" => \$port, 
         "fail=s" => \$fail_at); 

my @fail_at = split(/,/, $fail_at); 

# Opening file for log 
open (LOG, '>>', $outputfile); 

my $proxy = HTTP::Proxy->new; 
$proxy->port($port); 
$proxy->logfh(*LOG); 
$proxy->logmask(ALL); 

if ($fail_at[0] ne 'all') { 
    foreach my $url (@fail_at) { 
     $proxy->push_filter(
      host => $url, 
      response => HTTP::Proxy::BodyFilter::complete->new, 
      response => $Filters::Filter403::header, 
      response => $Filters::Filter403::body 
     ); 
    } 
} 
else { 
    $proxy->push_filter (
     response => HTTP::Proxy::BodyFilter::complete->new(), 
     response => $Filters::Filter403::header, 
     response => $Filters::Filter403::body 
    ); 
} 

my $pid = fork(); 

# Command for the forked process 
if (defined($pid) and $pid == 0) { 
    open (my $errfh, '>', $errorfile); 
    STDOUT->fdopen(\*$errfh, 'w') || die "Couldn't set STDERR to $errorfile: $!\n"; 
    $proxy->start; 
} 

# Command for the main script 
unless ($pid == 0) { 
    print "Proxy HTTP started on port $port with PID $pid.\n"; 
    print "You can read its output in $outputfile.\n"; 
} 

exit 0; 

你能帮我吗? 我试过Daxim的解决方案,我也尝试使用$ { $_[1] },因为文档似乎暗示,但它没有奏效。

非常感谢。

+0

您可以检查wget -S到代理以查看内容何时到期。如果提前10年,您需要进入该代理缓存。 – Andrew

回答

1

我已经找到了解决办法。 问题是HTTP::Proxy::BodyFilter::complete->new之后的每个过滤器都会执行空数据。我发现加载一个沉重的页面,我的代码被添加了多次。

这里是工作的过滤器:

our $body = HTTP::Proxy::BodyFilter::simple->new (
    sub { 
     my ($self, $dataref, $message, $protocol, $buffer) = @_; 
     unless (defined ($buffer)){ 
      my $html = 
        '<!DOCTYPE html>'. 
        '<html><head><title>403 Forbidden</title><style type="text/css">'. 
        'body { padding: 40pt; }'. 
        'body, h1, h2, p { color: #333; font-family: Arial, sans-serif; margin: 0; }'. 
        'div { width: 200px; background: #eee; padding: 2em; }'. 
        '</style></head><body><div><h1>403</h1><h2>Forbidden</h2></div></body></html>'; 

      $$dataref = $html; 
     } 
    } 
); 

这样,除非$缓冲区民主基金,即接收到整个响应,当过滤器没有做任何事情。

0

请参阅HTTP::Proxy::BodyFilter::complete

$proxy->push_filter(
    response => HTTP::Proxy::BodyFilter::complete->new, 
    response => HTTP::Proxy::BodyFilter::simple->new(sub { 
     $_[1] = \<<'HTML'; 
<!DOCTYPE html> 
<html><head><title>403 Forbidden</title><style type="text/css"> 
body { padding: 40pt; } 
body, h1, h2, p { color: #333; font-family: Arial, sans-serif; margin: 0; } 
div { width: 200px; background: #eee; padding: 2em; } 
</style></head><body><div><h1>403</h1><h2>Forbidden</h2></div></body></html> 
HTML 
    }), 
); 
+0

对不起,但这不适合我。我要用主脚本的代码更新帖子,所以你也可以在那里看看。 – Zagorax

+0

我找到了一个解决方案。谢谢你,因为我不会没有你对BodyFilter :: complete的建议。 – Zagorax

+0

我看到文档可以使用一些改进;我会为BooK提供一个补丁。我很高兴你知道你想要什么,可以将自己的答案标记为可接受的,因为它最符合问题。 – daxim