App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Download.pm view on Meta::CPAN
# Copyright 2007, 2008, 2009, 2010, 2011, 2013, 2015, 2016, 2017, 2018, 2020, 2023, 2024 Kevin Ryde
# This file is part of Chart.
#
# Chart is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3, or (at your option) any later version.
#
# Chart is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along
# with Chart. If not, see <http://www.gnu.org/licenses/>.
package App::Chart::Download;
use 5.010;
use strict;
use warnings;
use Carp 'carp','croak';
use Date::Calc;
use List::Util qw(min max);
use List::MoreUtils;
use Regexp::Common 'whitespace';
use Locale::TextDomain ('App-Chart');
use PerlIO::via::EscStatus;
use Tie::TZ;
use App::Chart;
use App::Chart::Database;
use App::Chart::DBI;
use App::Chart::TZ;
# uncomment this to run the ### lines
# use Smart::Comments;
use constant DEBUG => 0;
#------------------------------------------------------------------------------
sub http_code_is_allowed {
my ($aref, $code) = @_;
return (grep {$code eq $_} @{$aref // []}) > 0;
}
sub get {
my ($class, $url, %options) = @_;
### Download get(): $url
# URI object becomes string
$url = "$url";
my $ua = $options{'ua'} || do { require App::Chart::UserAgent;
App::Chart::UserAgent->instance };
$ua->cookie_jar ($options{'cookie_jar'}); # undef for none
### cookie_jar object: ($options{'cookie_jar'} // "").""
require HTTP::Request;
my $method = $options{'method'} || 'GET';
my @headers = (Referer => $options{'referer'});
my $data = $options{'data'};
if (defined $data) {
push @headers, 'Content-Type' => 'application/x-www-form-urlencoded';
}
my $req = HTTP::Request->new ($method, $url, \@headers, $data);
# possible override
if (my $user_agent = $options{'user_agent'}) {
$req->user_agent($user_agent);
}
my $etag = $options{'etag'};
my $lastmod = $options{'last_modified'};
if (my $key = $options{'url_tags_key'}) {
my $symbol = $options{'symbol'};
my $prev_url = App::Chart::Database->read_extra($symbol,"$key-URL");
if (defined $prev_url && $url eq $prev_url) {
$etag = App::Chart::Database->read_extra($symbol,"$key-ETag");
$lastmod = App::Chart::Database->read_extra($symbol,"$key-Last-Modified");
}
}
if ($etag) { $req->header ('If-None-Match' => $etag); }
if ($lastmod) { $req->header ('If-Modified-Since' => $lastmod); }
my $resp = $ua->request ($req);
# internal message from LWP when a keep-alive has missed the boat
if ($resp->status_line =~ /500 Server closed connection/i) {
substatus (__('retry'));
$resp = $ua->request ($req);
}
my $code = $resp->code;
if ($resp->is_success
|| ($options{'allow_401'} && $code == 401)
|| ($options{'allow_404'} && $code == 404)
|| (($etag || $lastmod) && $code == 304)
|| http_code_is_allowed($options{'allow_http_codes'}, $code)) {
substatus (__('processing'));
return $resp;
} else {
my $error = $resp->status_line . "\n";
if ($code == 500) {
$error .= $resp->decoded_content;
unless ($error =~ /\n$/s) { $error .= "\n"; }
}
croak "Cannot download $url\n" . $error;
}
}
#------------------------------------------------------------------------------
my $last_status = ''; # without substatus addition
sub download_message {
print join (' ',@_),"\n";
}
sub verbose_message {
if ($App::Chart::option{'verbose'}) {
print join (' ',@_),"\n";
}
}
( run in 0.873 second using v1.01-cache-2.11-cpan-7fcb06a456a )