Преглед изворни кода

Return 304 for most resources

George S. Baugh пре 3 година
родитељ
комит
5a76099e60
2 измењених фајлова са 12 додато и 3 уклоњено
  1. 8 3
      lib/TCMS.pm
  2. 4 0
      lib/Trog/Routes/HTML.pm

+ 8 - 3
lib/TCMS.pm

@@ -43,6 +43,7 @@ my %routes = %Trog::Routes::HTML::routes;
 @routes{keys(%roots)} = values(%roots);
 
 my %aliases = $data->aliases();
+my %etags;
 
 #1MB chunks
 my $CHUNK_SIZE = 1024000;
@@ -68,6 +69,13 @@ sub app {
 
     my $env = shift;
 
+    # Check eTags.  If we don't know about it, just assume it's good and lazily fill the cache
+    # XXX yes, this allows cache poisoning
+    if ($env->{HTTP_IF_NONE_MATCH}) {
+        $etags{$env->{REQUEST_URI}} = $env->{HTTP_IF_NONE_MATCH} unless exists $etags{$env->{REQUEST_URI}};
+        return [304, [], ['']] if $env->{HTTP_IF_NONE_MATCH} eq $etags{$env->{REQUEST_URI}};
+    }
+
     my $last_fetch = 0;
     if ($env->{HTTP_IF_MODIFIED_SINCE}) {
         $last_fetch = DateTime::Format::HTTP->parse_datetime($env->{HTTP_IF_MODIFIED_SINCE})->epoch();
@@ -187,14 +195,11 @@ sub _serve ($path, $start, $streaming=0, $last_fetch=0, $deflate=0) {
 
     push(@headers,'Cache-control' => $Trog::Vars::cache_control{revalidate});
 
-    #TODO Return 304 unchanged for files that haven't changed since the requestor reports they last fetched
     my $mt = (stat($path))[9];
     my $sz = (stat(_))[7];
     my @gm = gmtime($mt);
     my $now_string = strftime( "%a, %d %b %Y %H:%M:%S GMT", @gm );
     my $code = $mt > $last_fetch ? 200 : 304;
-    #XXX something broken about the above logic
-    $code=200;
 
     #XXX doing metadata=preload on videos doesn't work right?
     #push(@headers, "Content-Length: $sz");

+ 4 - 0
lib/Trog/Routes/HTML.pm

@@ -891,6 +891,9 @@ sub posts ($query, $direct=0) {
     } @posts;
     my @et = List::MoreUtils::singleton(@$tags, @tags_all);
 
+    # Set the eTag so that we don't get a re-fetch
+    $query->{etag} = "$posts[0]{id}-$posts[0]{version}";
+
     my $content = themed_render('posts.tx', {
         acls      => \@acls,
         can_edit  => $is_admin,
@@ -1292,6 +1295,7 @@ sub finish_render ($template, $vars, @headers) {
     my $cc = 'Cache-control';
     push(@headers, $ct => $vars->{contenttype});
     push(@headers, $cc => $vars->{cachecontrol}) if $vars->{cachecontrol};
+    push(@headers, 'ETag' => $vars->{etag}) if $vars->{etag};
 
     #Return data in the event the caller does not support deflate
     if (!$vars->{deflate}) {