App-DuckPAN
view release on metacpan or search on metacpan
lib/App/DuckPAN/Cmd/Server.pm view on Meta::CPAN
$self->app->emit_info("Starting up webserver...", "You can stop the webserver with Ctrl-C");
require App::DuckPAN::Web;
my $web = App::DuckPAN::Web->new(%web_args);
my $runner = Plack::Runner->new(
#loader => 'Restarter',
includes => ['lib'],
app => sub { $web->run_psgi($self->app, @_) },
);
#$runner->loader->watch("./lib");
$runner->parse_options("--port", $self->port);
exit $runner->run;
}
sub slurp_or_empty {
my ($self, $which) = @_;
my $cache_path = $self->asset_cache_path;
my $contents = '';
foreach my $which_file (grep { $_->{internal} } (@$which)) {
my $where = $which_file->{internal};
my $change_method = ($where =~ m/\.js$/) ? 'change_js' : ($where =~ m/\.css$/) ? 'change_css' : 'change_html';
$contents .= $self->make_source_comment($which_file) . $self->$change_method($where->slurp) if ($where->exists);
}
return $contents;
}
sub make_source_comment {
my ($self, $file_info) = @_;
my $comment = '';
my $internal = $file_info->{internal};
my $title = $file_info->{name} || $internal;
if ($internal =~ /js$/) {
$comment = '// ' . $title;
}
elsif ($internal =~ /css$/) {
$comment = '/* ' . $title . '*/';
}
elsif ($internal =~ /html$/) {
$comment = '<!-- ' . $title . ' -->';
}
return "\n$comment\n"; # Just two blank lines if we don't know how to comment for the file type.
}
# Force DuckPAN to ignore requests for certain files
# that are not needed (ie. d.js, s.js, g.js, post2.html)
sub change_js {
my ( $self, $js ) = @_;
$js =~ s!/([dsg]\d+?|duckduck|duckgo_dev)\.js\?!/?duckduckhack_ignore=1&!g;
$js =~ s!/post2\.html!/?duckduckhack_ignore=1&!g;
return $self->change_css($js);
}
# Rewrite all relative asset links in CSS
# Capture leading quote, insert $hostname, append filename
# E.g url("/assets/background.png") => url("http://duckduckgo.com/assets/background.png")
sub change_css {
my ( $self, $css ) = @_;
my $hostname = $self->hostname;
$css =~ s!:\s*url\((["'])?/!:url\($1http://$hostname/!g;
return $css;
}
sub change_html {
my ( $self, $html ) = @_;
my $root = HTML::TreeBuilder->new;
$root->parse($html);
my @a = $root->look_down(
"_tag", "a"
);
my @link = $root->look_down(
"_tag", "link"
);
# Make sure DuckPAN serves DDG CSS (already pulled down at startup)
# ie <link href="/s123.css"> becomes <link href="/?duckduckhack_css=1">
# Also rewrite relative links to hostname
my $has_css = 0;
for (@a, @link) {
if ($_->attr('type') && $_->attr('type') eq 'text/css') {
# We only want to load the CSS file once.
# We only load it once because /?duckduckhack_css=1 already has all of the CSS
# in a single page.
unless($has_css) {
$_->attr('href','/?duckduckhack_css=1');
$has_css = 1;
}
else {
$_->attr('href','/?duckduckhack_ignore=1');
}
}
elsif (defined $_->attr('href') && substr($_->attr('href'),0,1) eq '/') {
$_->attr('href','http://'.$self->hostname.''.$_->attr('href'));
}
}
my @script = $root->look_down(
"_tag", "script"
);
# Make sure DuckPAN serves DDG JS (already pulled down at startup)
# ie <link href="/d123.js"> becomes <link href="/?duckduckhack_js=1">
# Also rewrite relative links to hostname
# Temp Fix: Force ignore of d.js & duckduck.
# This logic needs to be improved!
my $has_ddh = 0;
for (@script) {
if (my $src = $_->attr('src')) {
next if ($src =~ m/^\/\?duckduckhack_/); # Already updated, no need to do again
if ($src =~ m/^\/(dpan\d+|duckpan)\.js/) {
if ($has_ddh){
( run in 2.418 seconds using v1.01-cache-2.11-cpan-d8267643d1d )