From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-4.0 required=3.0 tests=ALL_TRUSTED,BAYES_00 shortcircuit=no autolearn=ham autolearn_force=no version=3.4.2 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 8492B1F45F for ; Sat, 4 May 2019 22:23:35 +0000 (UTC) From: Eric Wong To: meta@public-inbox.org Subject: [PATCH] githttpbackend: support Last-Modified and If-Modified-Since Date: Sat, 4 May 2019 22:23:35 +0000 Message-Id: <20190504222335.10286-1-e@80x24.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit List-Id: This can be used to optimized frequent polling over dumb HTTP. I will try making git support dumb polling, one day: https://public-inbox.org/git/20190502085055.34kkll2deowat6il@dcvr/ --- lib/PublicInbox/GitHTTPBackend.pm | 14 ++++++++++++-- t/httpd.t | 28 ++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib/PublicInbox/GitHTTPBackend.pm b/lib/PublicInbox/GitHTTPBackend.pm index 57944a0..c69b693 100644 --- a/lib/PublicInbox/GitHTTPBackend.pm +++ b/lib/PublicInbox/GitHTTPBackend.pm @@ -84,9 +84,19 @@ sub static_result ($$$$) { my ($env, $h, $f, $type) = @_; return r(404) unless -f $f && -r _; # just in case it's a FIFO :P - # TODO: If-Modified-Since and Last-Modified? + my $mtime = (stat(_))[9]; + my $last_mod = time2str($mtime); + if (my $ims = $env->{HTTP_IF_MODIFIED_SINCE}) { + # RFC2616 14.25 allows exact date comparisons + return [304, [], [] ] if $ims eq $last_mod; + } + open my $in, '<', $f or return r(404); my $size = -s $in; + if ($mtime != (stat(_))[9]) { + # unlikely, not impossible for mtime to change before fstat + $last_mod = time2str((stat(_))[9]); + } my $len = $size; my $code = 200; push @$h, 'Content-Type', $type; @@ -97,7 +107,7 @@ sub static_result ($$$$) { return [ 416, $h, [] ]; } } - push @$h, 'Content-Length', $len; + push @$h, 'Content-Length', $len, 'Last-Modified', $last_mod; my $n = 65536; [ $code, $h, Plack::Util::inline_object(close => sub { close $in }, getline => sub { diff --git a/t/httpd.t b/t/httpd.t index 44df164..21daeb1 100644 --- a/t/httpd.t +++ b/t/httpd.t @@ -13,6 +13,7 @@ use File::Temp qw/tempdir/; use Cwd qw/getcwd/; use IO::Socket; use Socket qw(SO_KEEPALIVE IPPROTO_TCP TCP_NODELAY); +use PublicInbox::Spawn qw(which); require './t/common.perl'; # FIXME: too much setup @@ -93,6 +94,33 @@ EOF "http://$host:$port/$group", "$tmpdir/dumb.git"), 0, 'clone successful'); + my $curl = which('curl'); + SKIP: { + skip('curl missing', 6) unless defined $curl; + my $ldesc = "$tmpdir/dumb.git/description"; + my $rdesc = "$maindir/description"; + utime 12, 34, $rdesc; + + # initial retrieval + is(system(qw(curl -sSfR -z), $ldesc, '-o', $ldesc, + "http://$host:$port/$group/description"), + 0, 'initial curl retrieval OK'); + is((stat($ldesc))[9], (stat($rdesc))[9], 'curl set mtime'); + + # no modification + is(system(qw(curl -sSfR -z), $ldesc, '-o', "$ldesc.x", + "http://$host:$port/$group/description"), + 0, 'curl 304 OK'); + ok(!-f "$ldesc.x", 'no retrieval on 304'); + + # modification detected + utime 56, 78, $rdesc; + is(system(qw(curl -sSfR -z), $ldesc, '-o', $ldesc, + "http://$host:$port/$group/description"), + 0, 'curl updated file OK'); + is((stat($ldesc))[9], (stat($rdesc))[9], 'curl updates mtime'); + }; + ok(kill('TERM', $pid), 'killed httpd'); $pid = undef; waitpid(-1, 0); -- EW