[Tokyo.pm] HTTP::Winder
taguti
taguti @ secom-sis.co.jp
2002年 11月 7日 (木) 03:21:34 CST
久々登場、田口と申します。
「PAUSEの使いかた」は大よそ落着かと思いますが、
この件でメールしたくなりました。一応、スレッドは別で。
HTTP::Proxyってモジュール、CPANに出てるの、知ってます?
たまたま私、Proxyに近いことがやりたくてこれを参考に、
というか継承してプログラムを作成しました。
オブジェクト指向のモジュールは作成したことが無かったので
出来ばえのほうは良くわかりません。
作者にメール送ったんですが、Host unknownで返ってきました。
ホームページも繋がらないし。
これって怪しい人なんですかねー。
そう言えば、DAIBAさんっていうのも、ある意味...
HTTP::Winderを作成したきっかけは、こうです。
今運営しているサイトを何人かの人にデモする必要が出てきた
のですが、このサイトはパスワードがかかっています。
数人にメールでURLを教えたいのですが、パスワードは教えたくない。
現行のシステムを触りたくない。
パスワードを追加するProxyを作成して、そのProxyを
設定して閲覧するようにしてもいいんですが、ブラウザーにProxyを
設定するのはなんか面倒(と言われそう)。
それで関係者には、
"http://hostname:nnnn/hoo/bar.htm"
をメールで教えて、
同じサーバーにポートnnnnをリスンし、ユーザーとパスワードを
追加してリクエストを
"http://hostname/hoo/bar.htm"
に出すものを作成しようと考えました。
本当は別のサーバーにしたかったのですが、それはやり方が良く
判りませんでした。
"TCP tunnel"に似たようなものを作りたかったのですが。
で、こうゆうプログラムのことを何と呼ぶか判りますか?
これもProxyでしょうか?
良く判らないので私はWinderとつけました。本当はSidewinderと
したかったのですが、それだと長いので。(^_^;
ストレートに80番に行くのではなく、別ポートに来たリクエストを
巻きついて(絡み付いて)80番に飛ばすもの、という意味です。
ここのML、添付ファイル禁止ですか。
モジュールとサンプルのスクリプトを掲載します。
------------------------------------------ SampleWinder.pl
#!/usr/bin/perl
use HTTP::Winder;
use strict;
print STDERR "=== Winder :8000 ===\n";
my $winder_cb = sub {
my ($req) = shift;
$req = $$req;
$req->authorization_basic('scott', 'tiger');
};
my $winder = HTTP::Winder->new(verbose=>1,
host=>"myServer",
callback=>$winder_cb);
$winder->start;
------------------------------------------
------------------------------------------ HTTP::Winder.pm
package HTTP::Winder;
use base ("HTTP::Proxy");
use HTTP::Daemon;
use LWP::UserAgent;
use LWP::ConnCache;
use Data::Dumper;
use POSIX qw(WNOHANG);
use Fcntl ':flock';
use Carp;
use strict;
use vars qw( $VERSION $AUTOLOAD );
$VERSION = 0.01;
sub new {
my $class = shift;
my $self = {
agent => undef,
daemon => undef,
callback => undef,
host => 'localhost',
maxchild => 16,
maxconn => 0,
logfh => *STDERR,
port => 8000,
verbose => 0,
@_,
};
# non modifiable defaults
%$self = ( %$self, conn => 0 );
return bless $self, $class;
}
sub start {
my $self = shift;
$self->init;
$SIG{CHLD} = sub { do {} while waitpid(-1, WNOHANG) > 0 };
my $daemon = $self->daemon;
while ( my $conn = $daemon->accept ) {
my $child = fork;
if ( !defined $child ) {
# This could use a Retry-After: header...
$conn->send_error( 503, "IpRedir cannot fork" );
$self->log( 0, "Cannot fork" );
next;
}
if ($child) { # the parent process
$conn->close; # maybe...
undef $conn; # maybe...
$self->log( 3, "Forked child process $child" );
}
else {
# the child process handles the connection
$self->process($conn);
$conn->close;
undef $conn;
exit; # let's die!
}
}
$self->log( 0, "Done " . $self->conn . " connection(s)" );
return $self->conn;
}
sub process {
my ( $self, $conn ) = @_;
while ( my $req = $conn->get_request() ) {
unless ( defined $req ) {
$self->log( 0, "Getting request failed:", $conn->reason );
return;
}
my $callback = $self->{callback};
my $reqhost = $req->header('host');
my $requrl = $req->url();
print STDERR "Winder> reqhost=$reqhost, requrl=$requrl\n";
&$callback(\$req) if (defined $callback);
$reqhost =~ s/:\d+//;
$req->header('host', $reqhost);
$req->url('http://' . $reqhost . $requrl);
$self->log( 1, "($$) Request: " . $req->uri );
$self->log( 5, "($$) Request: " . $req->headers->as_string );
# handle the Connection: header from the request
my $res = $self->agent->simple_request($req);
$conn->print( $res->as_string );
$self->log( 1, "($$) Response: " . $res->status_line );
$self->log( 5, "($$) Response: " . $res->headers->as_string );
last;
}
}
1;
------------------------------------------
Hirosi Taguti
taguti @ secom-sis.co.jp
Tokyo-pm メーリングリストの案内