From: Jakub Narebski <jnareb@gmail.com>
To: git@vger.kernel.org
Cc: John 'Warthog9' Hawley <warthog9@kernel.org>,
John 'Warthog9' Hawley <warthog9@eaglescrag.net>,
Junio C Hamano <gitster@pobox.com>, demerphq <demerphq@gmail.com>,
Aevar Arnfjord Bjarmason <avarab@gmail.com>,
Thomas Adam <thomas@xteddy.org>,
Jakub Narebski <jnareb@gmail.com>
Subject: [RFC PATCH 24/24] gitweb: Add beginnings of cache administration page (proof of concept)
Date: Tue, 7 Dec 2010 00:11:09 +0100 [thread overview]
Message-ID: <1291677069-6559-25-git-send-email-jnareb@gmail.com> (raw)
In-Reply-To: <1291677069-6559-1-git-send-email-jnareb@gmail.com>
Currently cache administration page ('cache' action) shows estimated
size of cache, and provides link to clearing cache.
Cache administration page is visible only on local computer; the same
is true with respect to ability to clear cache. Those are bare
beginnings of autorization framework.
If you can use cache administration page, you will see 'admin' link at
the botom of the page to it.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This is "frontend" (interface) patch for gitweb cache management.
This is very much work in progress, sent to git mailing list as a
proof of concept. Would something like that (perhaps with more
advanced authorization for admin) be useful?
The 'cache' page looks like this:
Cache location Size
------------------+---------+--------------
cache/gitweb 14 KiB [Clear cache]
------------------+---------+--------------
where '[Clear cache]' is a submit button.
Compared to previous series there is now 'admin' link that leads to
cache administration page, which is present only if you have
permissions to access said page.
Also for empty cache we show '-'.
Code was made slightly safer, though still I wouldn't use it in
production, as there might be a chance that remote attacker could
possibly clear cache (meaning I didn't prove that it couldn't happen).
In the final version this patch should probably be split into a few
smaller commits, for example:
* adding support for $opts{'-title'} to git_header_html
* action_is_cacheable subroutine
* human_readable_size (which could also be used in 'tree' view at request)
* xxx_admin_auth_ok, i.e. authorization and authentication for admin and
write actions in gitweb
* 'cache' (i.e. cache admin) and 'clear_cache' (worker) methods
gitweb/gitweb.perl | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 134 insertions(+), 4 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 1521bf2..66e240f 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -25,6 +25,8 @@ use Encode;
use Fcntl qw(:mode :flock);
use File::Find qw();
use File::Basename qw(basename);
+use POSIX; # for POSIX::ceil($x)
+
binmode STDOUT, ':utf8';
our $t0;
@@ -888,6 +890,10 @@ sub evaluate_actions_info {
map { $actions_info{$_}{'output_format'} = undef }
qw(blob_plain object);
$actions_info{'snapshot'}{'output_format'} = 'binary';
+
+ # specify uncacheable actions
+ map { $actions_info{$_}{'uncacheable'} = 1 }
+ qw(cache clear_cache);
}
sub action_outputs_html {
@@ -895,6 +901,11 @@ sub action_outputs_html {
return $actions_info{$action}{'output_format'} eq 'html';
}
+sub action_is_cacheable {
+ my $action = shift;
+ return !$actions_info{$action}{'uncacheable'};
+}
+
sub browser_is_robot {
return 1 if !exists $ENV{'HTTP_USER_AGENT'}; # gitweb run as script
if (eval { require HTTP::BrowserDetect; }) {
@@ -1245,12 +1256,13 @@ sub dispatch {
if (!defined($actions{$action})) {
die_error(400, "Unknown action");
}
- if ($action !~ m/^(?:opml|project_list|project_index)$/ &&
+ if ($action !~ m/^(?:opml|project_list|project_index|cache|clear_cache)$/ &&
!$project) {
die_error(400, "Project needed");
}
- if ($caching_enabled) {
+ if ($caching_enabled &&
+ action_is_cacheable($action)) {
# human readable key identifying gitweb output
my $output_key = href(-replay => 1, -full => 1, -path_info => 0);
@@ -1397,6 +1409,10 @@ sub configure_caching {
require GitwebCache::Capture::Simple;
$capture = GitwebCache::Capture::Simple->new();
}
+
+ # some actions are available only if cache is turned on
+ $actions{'cache'} = \&git_cache_admin;
+ $actions{'clear_cache'} = \&git_cache_clear;
}
run();
@@ -3760,7 +3776,7 @@ sub git_header_html {
my $expires = shift;
my %opts = @_;
- my $title = get_page_title();
+ my $title = $opts{'-title'} || get_page_title();
my $content_type;
# require explicit support from the UA if we are to send the page as
# 'application/xhtml+xml', otherwise send it as plain old 'text/html'.
@@ -3936,10 +3952,18 @@ sub git_footer_html {
} else {
print $cgi->a({-href => href(project=>undef, action=>"opml"),
- -class => $feed_class}, "OPML") . " ";
+ -class => $feed_class}, "OPML") . "\n";
print $cgi->a({-href => href(project=>undef, action=>"project_index"),
-class => $feed_class}, "TXT") . "\n";
+
}
+
+ if ($actions{'cache'} &&
+ cache_admin_auth_ok()) {
+ print $cgi->a({-href => href(project=>undef, action=>"cache"),
+ -class => $feed_class}, "<i>admin</i>") . "\n";
+ }
+
print "</div>\n"; # class="page_footer"
# timing info doesn't make much sense with output (response) caching,
@@ -7412,3 +7436,109 @@ XML
</opml>
XML
}
+
+# see Number::Bytes::Human
+sub human_readable_size {
+ my $bytes = shift || return;
+
+ my @units = ('', 'KiB', 'MiB', 'GiB', 'TiB');
+ my $block = 1024;
+
+ my $x = $bytes;
+ my $unit;
+ foreach (@units) {
+ $unit = $_, last if POSIX::ceil($x) < $block;
+ $x /= $block;
+ }
+
+ my $num;
+ if ($x < 10.0) {
+ $num = sprintf("%.1f", POSIX::ceil($x*10)/10);
+ } else {
+ $num = sprintf("%d", POSIX::ceil($x));
+ }
+
+ return "$num $unit";
+}
+
+sub cache_admin_auth_ok {
+ if (defined $ENV{'REMOTE_ADDR'}) {
+ if (defined $ENV{'SERVER_ADDR'}) {
+ # SERVER_ADDR is not in RFC 3875
+ return $ENV{'SERVER_ADDR'} eq $ENV{'REMOTE_ADDR'};
+ } elsif ($ENV{'REMOTE_ADDR'} =~ m!^(?:127\.0\.0\.1|::1/128)$!) {
+ # localhost in IPv4 or IPv6
+ return 1;
+ }
+ } else {
+ # REMOTE_ADDR not defined, probably calling gitweb as script
+ return 1;
+ }
+
+ # restrict all but specified cases
+ return 0;
+}
+
+sub git_cache_admin {
+ $caching_enabled
+ or die_error(403, "Caching disabled");
+ cache_admin_auth_ok()
+ or die_error(403, "Cache administration not allowed");
+ $cache && ref($cache)
+ or die_error(500, "Cache is not present");
+
+ git_header_html(undef, undef,
+ -title => to_utf8($site_name) . " - Gitweb cache");
+
+ print <<'EOF_HTML';
+<table class="cache_admin">
+<tr><th>Cache location</th><th>Size</th><th> </th></tr>
+EOF_HTML
+ print '<tr class="light">' .
+ '<td class="path">' . esc_path($cache->path_to_namespace()) . '</td>' .
+ '<td>';
+ my $size;
+ if ($cache->can('size')) {
+ $size = $cache->size();
+ } elsif ($cache->can('get_size')) {
+ $size = $cache->get_size();
+ }
+ if (defined $size) {
+ print human_readable_size($size);
+ } else {
+ print '-';
+ }
+ print '</td><td>';
+ if ($cache->can('clear')) {
+ print $cgi->start_form({-method => "POST",
+ -action => $my_uri,
+ -enctype => CGI::URL_ENCODED}) .
+ $cgi->input({-name=>"a", -value=>"clear_cache", -type=>"hidden"}) .
+ $cgi->submit({-label => 'Clear cache'}) .
+ $cgi->end_form();
+ }
+ print <<'EOF_HTML';
+</td></tr>
+</table>
+EOF_HTML
+
+ git_footer_html();
+}
+
+sub git_cache_clear {
+ $caching_enabled
+ or die_error(403, "Caching disabled");
+ cache_admin_auth_ok()
+ or die_error(403, "Clearing cache not allowed");
+ $cache && ref($cache)
+ or die_error(500, "Cache is not present");
+
+ if ($cgi->request_method() eq 'POST') {
+
+ $cache->clear();
+ }
+
+ #print "cleared";
+ print $cgi->redirect(-uri => href(action=>'cache', -full=>1),
+ -status => '303 See Other');
+}
--
1.7.3
prev parent reply other threads:[~2010-12-06 23:17 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-06 23:10 [PATCHv6/RFC 00/24] gitweb: Simple file based output caching Jakub Narebski
2010-12-06 23:10 ` [PATCH 01/24] t/test-lib.sh: Export also GIT_BUILD_DIR in test_external Jakub Narebski
2010-12-06 23:10 ` [PATCH 02/24] gitweb: Prepare for splitting gitweb Jakub Narebski
2010-12-06 23:10 ` [PATCH 03/24] gitweb/lib - Very simple file based cache Jakub Narebski
2010-12-06 23:10 ` [PATCH 04/24] gitweb/lib - Stat-based cache expiration Jakub Narebski
2010-12-06 23:10 ` [PATCH 05/24] gitweb/lib - Regenerate entry if the cache file has size of 0 Jakub Narebski
2010-12-06 23:10 ` [PATCH 06/24] gitweb/lib - Simple output capture by redirecting STDOUT Jakub Narebski
2010-12-06 23:10 ` [PATCH 07/24] gitweb/lib - Cache captured output (using get/set) Jakub Narebski
2010-12-06 23:10 ` [PATCH 08/24] gitweb: Add optional output caching Jakub Narebski
2010-12-06 23:10 ` [PATCH 09/24] gitweb/lib - Adaptive cache expiration time Jakub Narebski
2010-12-06 23:10 ` [PATCH 10/24] gitweb/lib - Use CHI compatibile (compute method) caching interface Jakub Narebski
2010-12-06 23:10 ` [PATCH 11/24] gitweb/lib - capture output directly to cache entry file Jakub Narebski
2010-12-06 23:10 ` [PATCH 12/24] gitweb/lib - Use locking to avoid 'cache miss stampede' problem Jakub Narebski
2010-12-06 23:10 ` [PATCH 13/24] gitweb/lib - No need for File::Temp when locking Jakub Narebski
2010-12-06 23:10 ` [PATCH 14/24] gitweb/lib - Serve stale data when waiting for filling cache Jakub Narebski
2010-12-06 23:11 ` [PATCH 15/24] gitweb/lib - Regenerate (refresh) cache in background Jakub Narebski
2010-12-06 23:11 ` [PATCH 16/24] gitweb: Introduce %actions_info, gathering information about actions Jakub Narebski
2010-12-06 23:11 ` [PATCH 17/24] gitweb: Show appropriate "Generating..." page when regenerating cache Jakub Narebski
2010-12-06 23:11 ` [PATCH 18/24] gitweb/lib - Configure running 'generating_info' when generating data Jakub Narebski
2010-12-06 23:11 ` [PATCH 19/24] gitweb: Add startup delay to activity indicator for cache Jakub Narebski
2010-12-06 23:11 ` [PATCH/RFC 20/24] gitweb/lib - Add support for setting error handler in cache Jakub Narebski
2010-12-06 23:11 ` [PATCH/RFC 21/24] gitweb: Wrap die_error to use as error handler for caching engine Jakub Narebski
2010-12-06 23:11 ` [PATCH/RFC 22/24] gitweb: Support legacy options used by kernel.org " Jakub Narebski
2010-12-06 23:11 ` [RFC/PATCH 23/24] gitweb/lib - Add clear() and size() methods to caching interface Jakub Narebski
2010-12-06 23:11 ` Jakub Narebski [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1291677069-6559-25-git-send-email-jnareb@gmail.com \
--to=jnareb@gmail.com \
--cc=avarab@gmail.com \
--cc=demerphq@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=thomas@xteddy.org \
--cc=warthog9@eaglescrag.net \
--cc=warthog9@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).