App-DuckPAN

 view release on metacpan or  search on metacpan

lib/App/DuckPAN/Cmd/Server.pm  view on Meta::CPAN

				my $long_path  = $1;
				my $cache_name = $long_path;
				$cache_name =~ s#^.+(\.\d+\.\d+\.js)#locales$1#g;    # Turn long path into cacheable name
				unshift @{$self->page_info->{locales}},
				  {
					name     => 'Locales JS',
					internal => $cache_path->child($cache_name),
					external => $long_path
				  };
			}
		}
	}

    	my @cssfile;
	for (grep { $_->attr('type') && $_->attr('type') eq 'text/css' } @link) {
		if (my $href = $_->attr('href')) {
			# We're looking for txxx.css and sxxx.css.
			# style.css and static.css are for development mode.
			if ($href =~ m/^\/((?:[str]\d+|style|static|serp)\.css)/) {
				my $name = $1;
				push @cssfile, $name;
			}
		}
	}
    	foreach (sort @cssfile) {
    		my $name = $_;
		unshift @{$self->page_info->{css}},
		  {
			name     => $name . ' CSS',
			internal => $cache_path->child($name),
			external => $name
		  };
    	}

	# Check if we need to request any new assets from hostname, otherwise use cached copies
	foreach my $curr_asset (grep { defined $_ && $_->{internal} } map { @{$self->page_info->{$_}} } (qw(js templates css locales))) {
		$self->retrieve_and_cache($curr_asset, $from);
	}
}

sub retrieve_and_cache {
	my ($self, $asset, $sub_of) = @_;

	return unless ($asset->{internal} && $asset->{external});

	my $to_file    = $asset->{internal};
	my $path_start = (substr($asset->{external}, 0, 1) eq '/') ? '' : '/';
	my $url        = 'https://' . $self->hostname . $path_start . $asset->{external};
	my $prefix     = ($sub_of) ? '[via ' . $sub_of->{name} . '] ' : '';
	$prefix .= '[' . $asset->{name} . '] ';
	if ($to_file->exists && (time - $to_file->stat->ctime) < $self->app->cachesec) {
		$self->app->emit_debug($prefix . $to_file->basename . " recently cached -- no request made.");
	}
	else {
		$self->app->emit_debug($prefix . 'requesting from: ' . $url . '...');
		$to_file->remove;
		$to_file->touchpath;
		my ($expected_length, $bytes_received, $progress);
		my $next_update = 0;
		my $res         = $self->app->http->request(
			HTTP::Request->new(GET => $url),
			sub {
				my ($chunk, $res) = @_;
				$bytes_received += length($chunk);
				$to_file->append($chunk);
				$expected_length //= $res->content_length || 0;
				return unless $self->app->verbose;    # Progress bar is just for verbose mode;
				if ($expected_length && !defined($progress)) {
					$progress = Term::ProgressBar->new({
						name   => $prefix,
						count  => $expected_length,
						remove => 1,
						ETA    => 'linear',
						fh     => \*STDOUT,
					});
					$progress->minor(0);
				}
				elsif ($progress && $bytes_received > $next_update) {
					$next_update = $progress->update($bytes_received);
				}
			});
		if (!$res->is_success) {
			$self->app->emit_and_exit(1, qq~$prefix request failed with response: ~ . $res->status_line . "\n");
		}
		elsif ($expected_length && $bytes_received < $expected_length) {
			$to_file->remove;
			$self->app->emit_and_exit(1, qq~$prefix only $bytes_received of $expected_length bytes received~);
		}
		else {
			$progress->update($expected_length) if ($progress && $expected_length);
			$self->app->emit_debug($prefix . 'written to cache: ' . $to_file);
		}
	}
	# We need to load the assets on the SERPs for reuse.
	if ($asset->{load_sub_assets}) {
		$self->app->emit_debug($prefix . 'parsing for additional assets');
		$self->get_sub_assets($asset);
		$self->app->emit_debug($prefix . 'assets loaded');
	}

	return;
}

1;

__END__

=pod

=head1 NAME

App::DuckPAN::Cmd::Server - Starting up the web server to test instant answers

=head1 VERSION

version 1021

=head1 AUTHOR

DuckDuckGo <open@duckduckgo.com>, Zach Thompson <zach@duckduckgo.com>, Zaahir Moolla <moollaza@duckduckgo.com>, Torsten Raudssus <torsten@raudss.us> L<https://raudss.us/>



( run in 0.917 second using v1.01-cache-2.11-cpan-5a3173703d6 )