Reviewed by Maciej.
authorap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jul 2006 16:45:13 +0000 (16:45 +0000)
committerap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 4 Jul 2006 16:45:13 +0000 (16:45 +0000)
        - http://bugzilla.opendarwin.org/show_bug.cgi?id=8210
        Conditional XMLHttpRequest gets should pass 304 responses unchanged

        Test: http/tests/xmlhttprequest/cache-override.html

        * Misc/WebNSURLRequestExtras.h: Added _web_isConditionalRequest
        * Misc/WebNSURLRequestExtras.m:
        (-[NSURLRequest _web_isConditionalRequest]):
        * WebCoreSupport/WebFrameBridge.m:
        (-[WebFrameBridge syncLoadResourceWithMethod:URL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
        Bypass the cache for conditional requests.
        * WebCoreSupport/WebSubresourceLoader.m:
        (+[WebSubresourceLoader startLoadingResource:withRequest:customHeaders:referrer:forDataSource:]): Ditto.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15150 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/tests/xmlhttprequest/cache-override-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/cache-override.html [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/resources/304.pl [new file with mode: 0755]
WebKit/ChangeLog
WebKit/Misc/WebNSURLRequestExtras.h
WebKit/Misc/WebNSURLRequestExtras.m
WebKit/WebCoreSupport/WebFrameBridge.m
WebKit/WebCoreSupport/WebSubresourceLoader.m

index c06241ee263b98a81bbcdcdbbf97fb6bef01d715..a16fdcdbcfa2685c60353a2db976d3418988f1a5 100644 (file)
@@ -1,3 +1,14 @@
+2006-07-04  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Maciej.
+
+        - http://bugzilla.opendarwin.org/show_bug.cgi?id=8210
+        Conditional XMLHttpRequest gets should pass 304 responses unchanged
+
+        * http/tests/xmlhttprequest/cache-override-expected.txt: Added.
+        * http/tests/xmlhttprequest/cache-override.html: Added.
+        * http/tests/xmlhttprequest/resources/304.pl: Added.
+
 2006-07-02  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed by Darin.
diff --git a/LayoutTests/http/tests/xmlhttprequest/cache-override-expected.txt b/LayoutTests/http/tests/xmlhttprequest/cache-override-expected.txt
new file mode 100644 (file)
index 0000000..e87d03b
--- /dev/null
@@ -0,0 +1,29 @@
+Tests for bug 8210 - Conditional XMLHttpRequest gets should pass 304 responses unchanged.
+
+Fetching the resource once to cache the response...
+Automatically cached response body is correct; status = 200
+If-Modified-Since override: status = 304
+If-MODIFIED-Since override: status = 304
+If-Modified-Since override (modified): status = 200
+If-Unmodified-Since override: status = 200
+If-Unmodified-Since override (modified): status = 412
+If-Match override: status = 200
+If-Match override (none match): status = 412
+If-None-Match override: status = 304
+If-None-Match override (none match): status = 200
+If-Range override: status = 206
+If-Range override (none match): status = 200
+If-Modified-Since override (uncached response): status = 304
+async: Automatically cached response body is correct; status = 200
+async: If-Modified-Since override: status = 304
+async: If-Modified-Since override (modified): status = 200
+async: If-Unmodified-Since override: status = 200
+async: If-Unmodified-Since override (modified): status = 412
+async: If-Match override: status = 200
+async: If-Match override (none match): status = 412
+async: If-None-Match override: status = 304
+async: If-None-Match override (none match): status = 200
+async: If-Range override: status = 206
+async: If-Range override (none match): status = 200
+async: If-Modified-Since override (uncached response): status = 304
+
diff --git a/LayoutTests/http/tests/xmlhttprequest/cache-override.html b/LayoutTests/http/tests/xmlhttprequest/cache-override.html
new file mode 100644 (file)
index 0000000..3882391
--- /dev/null
@@ -0,0 +1,221 @@
+<html>
+<body>
+<p>Tests for <a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=8210"> bug 8210</a> - 
+Conditional XMLHttpRequest gets should pass 304 responses unchanged.</p>
+<script>
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    
+    var console_messages = document.createElement("ul");
+    document.body.appendChild(console_messages);
+    
+    function log(message)
+    {
+        var item = document.createElement("li");
+        item.appendChild(document.createTextNode(message));
+        console_messages.appendChild(item);
+    }
+
+    // sync
+    req = new XMLHttpRequest;
+    req.open("GET", "resources/reply.xml", false);
+    log("Fetching the resource once to cache the response...");
+    req.send(null);
+    lastModified = req.getResponseHeader("Last-Modified");
+    eTag = req.getResponseHeader("ETag");
+    
+    req.open("GET", "resources/reply.xml", false);
+    req.send(null);
+    if (req.responseText == '<?xml version="1.0" encoding="windows-1251"?>\n<node>Проверка</node>\n')
+        log("Automatically cached response body is correct; status = " + req.status);
+    else
+        log("Automatically cached response body is different from the expected one; status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Modified-Since", lastModified);
+    req.send(null);
+    log("If-Modified-Since override: status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-MODIFIED-Since", lastModified);
+    req.send(null);
+    log("If-MODIFIED-Since override: status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Modified-Since", "Tue, 01 Jan 1980 01:00:00 GMT");
+    req.send(null);
+    log("If-Modified-Since override (modified): status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Unmodified-Since", lastModified);
+    req.send(null);
+    log("If-Unmodified-Since override: status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Unmodified-Since", "Tue, 01 Jan 1980 01:00:00 GMT");
+    req.send(null);
+    log("If-Unmodified-Since override (modified): status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Match", eTag);
+    req.send(null);
+    log("If-Match override: status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Match", "xyzzy");
+    req.send(null);
+    log("If-Match override (none match): status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-None-Match", eTag);
+    req.send(null);
+    log("If-None-Match override: status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-None-Match", "xyzzy");
+    req.send(null);
+    log("If-None-Match override (none match): status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Range", eTag);
+    req.setRequestHeader("Range", "bytes=52-60");
+    req.send(null);
+    log("If-Range override: status = " + req.status);
+
+    req.open("GET", "resources/reply.xml", false);
+    req.setRequestHeader("If-Range", "xyzzy");
+    req.setRequestHeader("Range", "bytes=52-60");
+    req.send(null);
+    log("If-Range override (none match): status = " + req.status);
+
+    req.open("GET", "resources/304.pl", false);
+    req.setRequestHeader("If-Modified-Since", "Tue, 01 Jan 1980 01:00:00 GMT");
+    req.send(null);
+    log("If-Modified-Since override (uncached response): status = " + req.status);
+
+    // async
+    var asyncStep = 1;
+
+    req.onreadystatechange = processStateChange;
+    req.open("GET", "resources/reply.xml", true);
+    req.send(null);
+
+    function processStateChange() {
+    
+      if (req.readyState == 4){
+          if (asyncStep == 1) {
+            asyncStep = 2;
+            if (req.responseText == '<?xml version="1.0" encoding="windows-1251"?>\n<node>Проверка</node>\n')
+                log("async: Automatically cached response body is correct; status = " + req.status);
+            else
+                log("async: Automatically cached response body is different from the expected one; status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Modified-Since", lastModified);
+            req.send(null);
+          } else if (asyncStep == 2) {
+            asyncStep = 3;
+            log("async: If-Modified-Since override: status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Modified-Since", "Tue, 01 Jan 1980 01:00:00 GMT");
+            req.send(null);
+          } else if (asyncStep == 3) {
+            asyncStep = 4;
+            log("async: If-Modified-Since override (modified): status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Unmodified-Since", lastModified);
+            req.send(null);
+          } else if (asyncStep == 4) {
+            asyncStep = 5;
+            log("async: If-Unmodified-Since override: status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Unmodified-Since", "Tue, 01 Jan 1980 01:00:00 GMT");
+            req.send(null);
+          } else if (asyncStep == 5) {
+            asyncStep = 6;
+            log("async: If-Unmodified-Since override (modified): status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Match", eTag);
+            req.send(null);
+          } else if (asyncStep == 6) {
+            asyncStep = 7;
+            log("async: If-Match override: status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Match", "xyzzy");
+            req.send(null);
+          } else if (asyncStep == 7) {
+            asyncStep = 8;
+            log("async: If-Match override (none match): status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-None-Match", eTag);
+            req.send(null);
+          } else if (asyncStep == 8) {
+            asyncStep = 9;
+            log("async: If-None-Match override: status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-None-Match", "xyzzy");
+            req.send(null);
+          } else if (asyncStep == 9) {
+            asyncStep = 10;
+            log("async: If-None-Match override (none match): status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Range", eTag);
+            req.setRequestHeader("Range", "bytes=52-59");
+            req.send(null);
+          } else if (asyncStep == 10) {
+            asyncStep = 11;
+            log("async: If-Range override: status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/reply.xml", true);
+            req.setRequestHeader("If-Range", "xyzzy");
+            req.setRequestHeader("Range", "bytes=52-59");
+            req.send(null);
+          } else if (asyncStep == 11) {
+            asyncStep = 12;
+            log("async: If-Range override (none match): status = " + req.status);
+
+            req = new XMLHttpRequest();
+            req.onreadystatechange = processStateChange;
+            req.open("GET", "resources/304.pl", true);
+            req.setRequestHeader("If-Modified-Since", "Tue, 01 Jan 1980 01:00:00 GMT");
+            req.send(null);
+          } else if (asyncStep == 12) {
+            log("async: If-Modified-Since override (uncached response): status = " + req.status);
+            if (window.layoutTestController)
+              layoutTestController.notifyDone();
+          }
+        }
+    }
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/xmlhttprequest/resources/304.pl b/LayoutTests/http/tests/xmlhttprequest/resources/304.pl
new file mode 100755 (executable)
index 0000000..d4d42c4
--- /dev/null
@@ -0,0 +1,5 @@
+#!/usr/bin/perl
+# Simple script to generate a 304 HTTP status
+
+print "Status: 304 Not Modified\r\n";
+print "\r\n";
index edc1f9ea1afd5562ff314ac23d1a1a86d457f463..1a29fcb263e2e262df92263607e4ff2cb287dd3d 100644 (file)
@@ -1,3 +1,21 @@
+2006-07-04  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Maciej.
+
+        - http://bugzilla.opendarwin.org/show_bug.cgi?id=8210
+        Conditional XMLHttpRequest gets should pass 304 responses unchanged
+
+        Test: http/tests/xmlhttprequest/cache-override.html
+
+        * Misc/WebNSURLRequestExtras.h: Added _web_isConditionalRequest
+        * Misc/WebNSURLRequestExtras.m:
+        (-[NSURLRequest _web_isConditionalRequest]):
+        * WebCoreSupport/WebFrameBridge.m:
+        (-[WebFrameBridge syncLoadResourceWithMethod:URL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
+        Bypass the cache for conditional requests.
+        * WebCoreSupport/WebSubresourceLoader.m:
+        (+[WebSubresourceLoader startLoadingResource:withRequest:customHeaders:referrer:forDataSource:]): Ditto.
+
 2006-07-01  David Kilzer  <ddkilzer@kilzer.net>
 
         Reviewed by NOBODY (fixed Tim's build fix).
index 908d05bfd05a4e54bcfa88a7c6367cbee0e4a94a..5dc30a2d859e78633ab92dc1191fe1ca7cc64efc 100644 (file)
@@ -32,7 +32,7 @@
 
 - (NSString *)_web_HTTPReferrer;
 - (NSString *)_web_HTTPContentType;
-
+- (BOOL)_web_isConditionalRequest;
 @end
 
 @interface NSMutableURLRequest (WebNSURLRequestExtras)
index e60ecc311393e8e599b5926f3d0eb4fb6be47fc8..f2b76543c390e6faf0f69dc01d7b124ec02aeb4e 100644 (file)
     return [self valueForHTTPHeaderField:WebContentType];
 }
 
+- (BOOL)_web_isConditionalRequest
+{
+    if ([self valueForHTTPHeaderField:@"If-Match"] ||
+        [self valueForHTTPHeaderField:@"If-Modified-Since"] ||
+        [self valueForHTTPHeaderField:@"If-None-Match"] ||
+        [self valueForHTTPHeaderField:@"If-Range"] ||
+        [self valueForHTTPHeaderField:@"If-Unmodified-Since"])
+        return YES;
+    return NO;
+}
+
 @end
 
 
index 73b0c01f396092642c1436421d42fa015fe77ec3..e091837a2cfa221f8b0b349180e0b45c63f1671a 100644 (file)
@@ -573,7 +573,10 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
         [request addValue:[requestHeaders objectForKey:key] forHTTPHeaderField:key];
     }
     
-    [request setCachePolicy:[[[self dataSource] request] cachePolicy]];
+    if ([request _web_isConditionalRequest])
+        [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
+    else
+        [request setCachePolicy:[[[self dataSource] request] cachePolicy]];
     if (!hideReferrer)
         [request _web_setHTTPReferrer:[self referrer]];
     
index 089640dd8fe6156c05ab9de44e8b258a3b7e6bd2..2b3ee0260d8b0428d9455b9788e1bab64c7f70f9 100644 (file)
     // 2. Delegates that modify the cache policy using willSendRequest: should
     //    not affect any other resources. Such changes need to be done
     //    per request.
-    [newRequest setCachePolicy:[[source _originalRequest] cachePolicy]];
+    if ([newRequest _web_isConditionalRequest])
+        [newRequest setCachePolicy:NSURLRequestReloadIgnoringCacheData];
+    else
+        [newRequest setCachePolicy:[[source _originalRequest] cachePolicy]];
     [newRequest _web_setHTTPReferrer:referrer];
     
     [[source webFrame] _addExtraFieldsToRequest:newRequest mainResource:NO alwaysFromRequest:NO];