package POEDaemon::HTTPClient; use strict; use warnings FATAL => 'all'; no warnings 'redefine'; use Data::Dumper; use HTTP::Request; use POE qw(Component::Client::HTTP); use POEDaemon; sub states { return $_[0], [qw( httpclient_start httpclient_stop httpclient_request httpclient_response httpclient_response_test )]; } sub httpclient_start { my ($kernel, $heap) = @_[KERNEL, HEAP]; my $ua = cfg->{httpclient_useragent}; my $from = cfg->{httpclient_from}; my $proxy = cfg->{httpclient_proxy}; my $noproxy = cfg->{httpclient_noproxy}; my $default_ua = 'SHCP/0.1'; $heap->{httpclient}->{default_ua} = $default_ua; unless (defined $ua) { my $ua_extra = cfg->{shcp}->{http_useragent_extra}; if (defined $ua_extra && length $ua_extra) { foreach ($ua_extra) { s/^\s+//; s/\s+$//; } $heap->{httpclient}->{ua_extra} = $ua_extra; $ua = sprintf "%s (%s)", $default_ua, $ua_extra; } else { $ua = $default_ua; } } log_enabled && logline 'POE::Component::Client::HTTP->spawn'; my $connection_manager = POE::Component::Client::Keepalive->new ( keep_alive => 120, max_open => 50, max_per_host => 10, timeout => 60, ); POE::Component::Client::HTTP->spawn ( ($ua ? (Agent => $ua) : ()), ($from ? (From => $from) : ()), ($proxy ? (Proxy => $proxy) : ()), ($noproxy ? (NoProxy => $noproxy) : ()), ($connection_manager ? (ConnectionManager => $connection_manager) : ()), Alias => 'http', Timeout => 60, MaxSize => 1048576, FollowRedirects => 3, ); if (0) { foreach (0 .. 2) { $kernel->yield(httpclient_request => { url => 'http://dome.si.pri.ee/ip', response_event => 'httpclient_response_test', strip_whitespace => 1, }); } } if (0) { $kernel->yield(httpclient_request => { url => 'http://dome.si.pri.ee/yourinfo', response_event => 'httpclient_response_test', }); } } sub httpclient_stop { my ($kernel, $heap) = @_[KERNEL, HEAP]; delete $heap->{httpclient}; $kernel->post(http => 'shutdown'); } sub httpclient_request { my ($kernel, $heap, $args) = @_[KERNEL, HEAP, ARG0]; my $url = $args->{url}; my $response_event = $args->{response_event}; my $client_addr = $args->{client_addr}; my $client_port = $args->{client_port}; my $client_useragent = $args->{client_useragent}; unless (defined $url) { log_enabled && logline 'invalid url'; return; } unless (defined $response_event) { log_enabled && logline 'invalid response_event'; return; } foreach ($url) { s/^\s+//; s/\s+$//; } my $cache = $heap->{httpclient}->{cache}->{$url}; if ($cache) { my $time = $cache->{time}; if ($time && (time_hires - $time) <= 30) { my $content = $cache->{content}; my $content_type = $cache->{content_type}; $kernel->yield($response_event => { content => $content, content_type => $content_type, orig_args => $args, }); return; } } return if $heap->{httpclient}->{requests}->{$url}; my $http_default_ua = $heap->{httpclient}->{default_ua} || ''; my $http_ua_extra = $heap->{httpclient}->{ua_extra}; my @ua_comment; push @ua_comment, $http_ua_extra if $http_ua_extra; if ($client_addr && $client_port) { push @ua_comment, sprintf "remote=[%s]:%s", $client_addr, $client_port; } if ($client_useragent) { my $client_ua = $client_useragent; $client_ua =~ tr/(;)/[:]/; push @ua_comment, sprintf "ua=%s", $client_ua; } my $request_dynamic_ua = sprintf "%s%s", $http_default_ua, (@ua_comment ? sprintf " (%s)", join '; ', @ua_comment : ''); my $request = HTTP::Request->new(GET => $url => ($request_dynamic_ua ? [ 'User-Agent', $request_dynamic_ua ] : [])); $heap->{httpclient}->{requests}->{$url} = { orig_args => $args, }; $kernel->post(http => request => httpclient_response => $request); } sub httpclient_response { my ($kernel, $heap, $request_packet, $response_packet) = @_[KERNEL, HEAP, ARG0, ARG1]; my $request = $request_packet->[0]; my $response = $response_packet->[0]; my $url = sprintf "%s", $request->uri; my $content_type = $response->header('Content-Type'); my $content = $response->content; my $active_request = delete $heap->{httpclient}->{requests}->{$url}; my $orig_args = $active_request->{orig_args}; my $response_event = $orig_args->{response_event}; my $strip_whitespace = $orig_args->{strip_whitespace}; if ($strip_whitespace) { foreach ($content) { s/^\s+//; s/\s+$//; } } $heap->{httpclient}->{cache}->{$url} = { time => time_hires, content => $content, content_type => $content_type, }; $kernel->yield($response_event => { content => $content, content_type => $content_type, orig_args => $orig_args, }); } sub httpclient_response_test { my ($kernel, $args) = @_[KERNEL, ARG0]; log_enabled && logline "args:\n%s", Dumper $args; } 1;