subversion-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From svn-r...@apache.org
Subject svn commit: r1870739 - in /subversion/branches/1.10.x: ./ STATUS subversion/mod_dav_svn/repos.c subversion/tests/cmdline/mod_dav_svn_tests.py
Date Tue, 03 Dec 2019 04:00:09 GMT
Author: svn-role
Date: Tue Dec  3 04:00:09 2019
New Revision: 1870739

URL: http://svn.apache.org/viewvc?rev=1870739&view=rev
Log:
Merge r1866425 from trunk:

 * r1866425
   mod_dav_svn: Set Last-Modified response header for 'external' GET requests.
   Justification:
     The Last-Modified header was removed in r1724790 for performance reasons.
     However, for external requests the Last-Modified header is needed for
     certain use cases. Bringing it back only for external requests fixes
     these, while keeping the performance gain for checkout / update.
   Votes:
     +1: jcorvel, brane, rhuijben

Modified:
    subversion/branches/1.10.x/   (props changed)
    subversion/branches/1.10.x/STATUS
    subversion/branches/1.10.x/subversion/mod_dav_svn/repos.c
    subversion/branches/1.10.x/subversion/tests/cmdline/mod_dav_svn_tests.py

Propchange: subversion/branches/1.10.x/
------------------------------------------------------------------------------
  Merged /subversion/trunk:r1866425

Modified: subversion/branches/1.10.x/STATUS
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/STATUS?rev=1870739&r1=1870738&r2=1870739&view=diff
==============================================================================
--- subversion/branches/1.10.x/STATUS (original)
+++ subversion/branches/1.10.x/STATUS Tue Dec  3 04:00:09 2019
@@ -34,13 +34,3 @@ Veto-blocked changes:
 
 Approved changes:
 =================
-
- * r1866425
-   mod_dav_svn: Set Last-Modified response header for 'external' GET requests.
-   Justification:
-     The Last-Modified header was removed in r1724790 for performance reasons.
-     However, for external requests the Last-Modified header is needed for
-     certain use cases. Bringing it back only for external requests fixes
-     these, while keeping the performance gain for checkout / update.
-   Votes:
-     +1: jcorvel, brane, rhuijben

Modified: subversion/branches/1.10.x/subversion/mod_dav_svn/repos.c
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/subversion/mod_dav_svn/repos.c?rev=1870739&r1=1870738&r2=1870739&view=diff
==============================================================================
--- subversion/branches/1.10.x/subversion/mod_dav_svn/repos.c (original)
+++ subversion/branches/1.10.x/subversion/mod_dav_svn/repos.c Tue Dec  3 04:00:09 2019
@@ -3139,6 +3139,50 @@ seek_stream(dav_stream *stream, apr_off_
        && resource->baselined))
 
 
+/* Return the last modification time of RESOURCE, or -1 if the DAV
+   resource type is not handled, or if an error occurs.  Temporary
+   allocations are made from RESOURCE->POOL. */
+static apr_time_t
+get_last_modified(const dav_resource *resource)
+{
+  apr_time_t last_modified;
+  svn_error_t *serr;
+  svn_revnum_t created_rev;
+  svn_string_t *date_time;
+
+  if (RESOURCE_LACKS_ETAG_POTENTIAL(resource))
+    return -1;
+
+  if ((serr = svn_fs_node_created_rev(&created_rev, resource->info->root.root,
+                                      resource->info->repos_path,
+                                      resource->pool)))
+    {
+      svn_error_clear(serr);
+      return -1;
+    }
+
+  if ((serr = svn_fs_revision_prop2(&date_time, resource->info->repos->fs,
+                                    created_rev, SVN_PROP_REVISION_DATE,
+                                    TRUE, resource->pool, resource->pool)))
+    {
+      svn_error_clear(serr);
+      return -1;
+    }
+
+  if (date_time == NULL || date_time->data == NULL)
+    return -1;
+
+  if ((serr = svn_time_from_cstring(&last_modified, date_time->data,
+                                    resource->pool)))
+    {
+      svn_error_clear(serr);
+      return -1;
+    }
+
+  return last_modified;
+}
+
+
 const char *
 dav_svn__getetag(const dav_resource *resource, apr_pool_t *pool)
 {
@@ -3219,6 +3263,23 @@ set_headers(request_rec *r, const dav_re
   if (!resource->exists)
     return NULL;
 
+  if ((resource->type == DAV_RESOURCE_TYPE_REGULAR) 
+      && (resource->info->repos_path == resource->info->uri_path->data))
+    {
+      /* Include Last-Modified header for 'external' GET or HEAD requests
+         (i.e. requests to URI's not under /!svn), to support usage of an
+         SVN server as a file server, where the client needs timestamps
+         for instance to use as "last modification time" of files on disk. */
+      const apr_time_t last_modified = get_last_modified(resource);
+      if (last_modified != -1)
+        {
+          /* Note the modification time for the requested resource, and
+             include the Last-Modified header in the response. */
+          ap_update_mtime(r, last_modified);
+          ap_set_last_modified(r);
+        }  
+    }
+
   /* generate our etag and place it into the output */
   apr_table_setn(r->headers_out, "ETag",
                  dav_svn__getetag(resource, resource->pool));

Modified: subversion/branches/1.10.x/subversion/tests/cmdline/mod_dav_svn_tests.py
URL: http://svn.apache.org/viewvc/subversion/branches/1.10.x/subversion/tests/cmdline/mod_dav_svn_tests.py?rev=1870739&r1=1870738&r2=1870739&view=diff
==============================================================================
--- subversion/branches/1.10.x/subversion/tests/cmdline/mod_dav_svn_tests.py (original)
+++ subversion/branches/1.10.x/subversion/tests/cmdline/mod_dav_svn_tests.py Tue Dec  3 04:00:09
2019
@@ -640,6 +640,53 @@ def propfind_propname(sbox):
   actual_response = r.read()
   verify_xml_response(expected_response, actual_response)
 
+@SkipUnless(svntest.main.is_ra_type_dav)
+def last_modified_header(sbox):
+  "verify 'Last-Modified' header on 'external' GETs"
+
+  sbox.build(create_wc=False, read_only=True)
+
+  headers = {
+    'Authorization': 'Basic ' + base64.b64encode(b'jconstant:rayjandom').decode(),
+  }
+
+  h = svntest.main.create_http_connection(sbox.repo_url)
+
+  # GET /repos/iota
+  # Expect to see a Last-Modified header.
+  h.request('GET', sbox.repo_url + '/iota', None, headers)
+  r = h.getresponse()
+  if r.status != httplib.OK:
+    raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason))
+  svntest.verify.compare_and_display_lines(None, 'Last-Modified',
+                                           svntest.verify.RegexOutput('.+'),
+                                           r.getheader('Last-Modified'))
+  r.read()
+
+  # HEAD /repos/iota
+  # Expect to see a Last-Modified header.
+  h.request('HEAD', sbox.repo_url + '/iota', None, headers)
+  r = h.getresponse()
+  if r.status != httplib.OK:
+    raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason))
+  svntest.verify.compare_and_display_lines(None, 'Last-Modified',
+                                           svntest.verify.RegexOutput('.+'),
+                                           r.getheader('Last-Modified'))
+  r.read()
+
+  # GET /repos/!svn/rvr/1/iota
+  # There should not be a Last-Modified header (it's costly and not useful,
+  # see r1724790)
+  h.request('GET', sbox.repo_url + '/!svn/rvr/1/iota', None, headers)
+  r = h.getresponse()
+  if r.status != httplib.OK:
+    raise svntest.Failure('Request failed: %d %s' % (r.status, r.reason))
+  last_modified = r.getheader('Last-Modified')
+  if last_modified:
+    raise svntest.Failure('Unexpected Last-Modified header: %s' % last_modified)
+  r.read()
+
+  
 ########################################################################
 # Run the tests
 
@@ -652,6 +699,7 @@ test_list = [ None,
               propfind_404,
               propfind_allprop,
               propfind_propname,
+              last_modified_header,
              ]
 serial_only = True
 



Mime
View raw message