Reviewed by Darin.
authorap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Mar 2006 17:54:36 +0000 (17:54 +0000)
committerap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 1 Mar 2006 17:54:36 +0000 (17:54 +0000)
        - http://bugzilla.opendarwin.org/show_bug.cgi?id=3812
          XMLHttpRequest: PUT, DELETE, HEAD and all other methods but POST actually do a GET.

        HEAD is currently unimplemented because of what seems to be a bug in NSURLConnection,
        and does a GET instead.

WebCore:
        * kwq/KWQKJobClasses.h: Add a method parameter to TransferJob.
        * kwq/KWQKJobClasses.mm:
        (WebCore::TransferJobPrivate::TransferJobPrivate):
        (WebCore::TransferJob::TransferJob):
        (WebCore::TransferJob::method):
        * bridge/mac/WebCoreFrameBridge.h: URL loading functions now take a method parameter.
        * dom/xml_tokenizer.cpp:
        (WebCore::openFunc):
        * khtml/xsl/xslt_processorimpl.cpp:
        (DOM::docLoaderFunc):
        * kwq/KWQLoader.mm:
        (KWQServeRequest):
        (KWQServeSynchronousRequest):
        * loader/loader.cpp:
        (WebCore::Loader::servePendingRequests):
        * page/Frame.cpp:
        (WebCore::Frame::didOpenURL):
        * xml/xmlhttprequest.cpp:
        (WebCore::XMLHttpRequest::send): Honor the method passed in open().
        * khtml/ecma/JSXMLHttpRequest.cpp:
        (KJS::JSXMLHttpRequestProtoFunc::callAsFunction): Don't serialize null as "null".

WebKit:
        All WebKit changes are to use the method parameter passed from WebCore.

        * WebCoreSupport/WebFrameBridge.m:
        (-[WebFrameBridge startLoadingResource:withMethod:URL:customHeaders:]):
        (-[WebFrameBridge startLoadingResource:withMethod:URL:customHeaders:postData:]):
        (-[WebFrameBridge syncLoadResourceWithMethod:URL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
        * WebCoreSupport/WebSubresourceLoader.h:
        * WebCoreSupport/WebSubresourceLoader.m:
        (+[WebSubresourceLoader startLoadingResource:withMethod:URL:customHeaders:referrer:forDataSource:]):
        (+[WebSubresourceLoader startLoadingResource:withMethod:URL:customHeaders:postData:referrer:forDataSource:]):

LayoutTests:
        * http/tests/xmlhttprequest/methods-async-expected.txt: Added.
        * http/tests/xmlhttprequest/methods-async.html: Added.
        * http/tests/xmlhttprequest/methods-expected.txt: Added.
        * http/tests/xmlhttprequest/methods.cgi: Added.
        * http/tests/xmlhttprequest/methods.html: Added.

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/xmlhttprequest/methods-async-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/methods-async.html [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/methods-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/xmlhttprequest/methods.cgi [new file with mode: 0755]
LayoutTests/http/tests/xmlhttprequest/methods.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/bridge/mac/WebCoreFrameBridge.h
WebCore/dom/xml_tokenizer.cpp
WebCore/khtml/ecma/JSXMLHttpRequest.cpp
WebCore/khtml/xsl/xslt_processorimpl.cpp
WebCore/kwq/KWQKJobClasses.h
WebCore/kwq/KWQKJobClasses.mm
WebCore/kwq/KWQLoader.mm
WebCore/loader/loader.cpp
WebCore/page/Frame.cpp
WebCore/xml/xmlhttprequest.cpp
WebKit/ChangeLog
WebKit/WebCoreSupport/WebFrameBridge.m
WebKit/WebCoreSupport/WebSubresourceLoader.h
WebKit/WebCoreSupport/WebSubresourceLoader.m

index 34807b01de3b1cff95517bdaad40ba330fddd67e..9ef6feb8f2bcb474f36f3175f79b537cb976ec3d 100644 (file)
@@ -1,3 +1,16 @@
+2006-03-01  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Darin.
+
+        - Tests for http://bugzilla.opendarwin.org/show_bug.cgi?id=3812
+          XMLHttpRequest: PUT, DELETE, HEAD and all other methods but POST actually do a GET.
+
+        * http/tests/xmlhttprequest/methods-async-expected.txt: Added.
+        * http/tests/xmlhttprequest/methods-async.html: Added.
+        * http/tests/xmlhttprequest/methods-expected.txt: Added.
+        * http/tests/xmlhttprequest/methods.cgi: Added.
+        * http/tests/xmlhttprequest/methods.html: Added.
+
 2006-03-01  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed by Hyatt.
diff --git a/LayoutTests/http/tests/xmlhttprequest/methods-async-expected.txt b/LayoutTests/http/tests/xmlhttprequest/methods-async-expected.txt
new file mode 100644 (file)
index 0000000..cd8e48f
--- /dev/null
@@ -0,0 +1,21 @@
+Tests for bug 3812 - GET and POST should not be the only HTTP methods implemented in XMLHttpRequest.
+
+GET(""): GET(undefined bytes), Content-Type: undefined
+GET(null): GET(undefined bytes), Content-Type: undefined
+GET("123"): GET(undefined bytes), Content-Type: undefined
+POST(""): POST(0 bytes), Content-Type: application/xml
+POST(null): POST(0 bytes), Content-Type: undefined
+POST("123"): POST(3 bytes), Content-Type: application/xml
+PUT(""): PUT(0 bytes), Content-Type: application/xml
+PUT(null): PUT(0 bytes), Content-Type: undefined
+PUT("123"): PUT(3 bytes), Content-Type: application/xml
+DELETE(""): DELETE(0 bytes), Content-Type: application/xml
+DELETE(null): DELETE(0 bytes), Content-Type: undefined
+DELETE("123"): DELETE(3 bytes), Content-Type: application/xml
+WKFOOBAR(""): WKFOOBAR(0 bytes), Content-Type: application/xml
+WKFOOBAR(null): WKFOOBAR(0 bytes), Content-Type: undefined
+WKFOOBAR("123"): WKFOOBAR(3 bytes), Content-Type: application/xml
+SEARCH(""): SEARCH(0 bytes), Content-Type: application/xml
+SEARCH(null): SEARCH(0 bytes), Content-Type: undefined
+SEARCH("123"): SEARCH(3 bytes), Content-Type: application/xml
+
diff --git a/LayoutTests/http/tests/xmlhttprequest/methods-async.html b/LayoutTests/http/tests/xmlhttprequest/methods-async.html
new file mode 100644 (file)
index 0000000..3a1309f
--- /dev/null
@@ -0,0 +1,148 @@
+<html>
+<body>
+<p>Tests for <a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=3812"> bug 3812</a> - 
+GET and POST should not be the only HTTP methods implemented in XMLHttpRequest.</p>
+<script>
+    if (window.layoutTestController) {
+        layoutTestController.dumpAsText();
+        layoutTestController.waitUntilDone();
+    }
+    
+    var console_messages = document.createElement("ol");
+    document.body.appendChild(console_messages);
+    
+    function log(message)
+    {
+        var item = document.createElement("li");
+        item.appendChild(document.createTextNode(message));
+        console_messages.appendChild(item);
+    }
+
+    // async
+    
+    var asyncStep = 1;
+
+    req = new XMLHttpRequest;
+    req.onreadystatechange = processStateChange;
+    req.open("GET", "methods.cgi", true);
+    req.send("");
+
+    function processStateChange() {
+    
+      if (req.readyState == 4){
+        if (req.status == 200){
+           if (asyncStep == 1) {
+             asyncStep = 2;
+             log('GET(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("GET", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 2) {
+             asyncStep = 3;
+             log('GET(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("GET", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 3) {
+             asyncStep = 4;
+             log('GET("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("POST", "methods.cgi", true);
+             req.send("");
+           } else if (asyncStep == 4) {
+             asyncStep = 5;
+             log('POST(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("POST", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 5) {
+             asyncStep = 6;
+             log('POST(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("POST", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 6) {
+             asyncStep = 7;
+             log('POST("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("PUT", "methods.cgi", true);
+             req.send("");
+           } else if (asyncStep == 7) {
+             asyncStep = 8;
+             log('PUT(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("PUT", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 8) {
+             asyncStep = 9;
+             log('PUT(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("PUT", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 9) {
+             asyncStep = 10;
+             log('PUT("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("DELETE", "methods.cgi", true);
+             req.send("");
+           } else if (asyncStep == 10) {
+             asyncStep = 11;
+             log('DELETE(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("DELETE", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 11) {
+             asyncStep = 15;// 12;
+             log('DELETE(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("DELETE", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 12) {
+             asyncStep = 13;
+             log('DELETE("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("HEAD", "methods.cgi", true);
+             req.send("");
+           } else if (asyncStep == 13) {
+             asyncStep = 14;
+             log('HEAD(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("HEAD", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 14) {
+             asyncStep = 15;
+             log('HEAD(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("HEAD", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 15) {
+             asyncStep = 16;
+             log('DELETE("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             //log('HEAD("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("WKFOOBAR", "methods.cgi", true);
+             req.send("");
+           } else if (asyncStep == 16) {
+             asyncStep = 17;
+             log('WKFOOBAR(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("WKFOOBAR", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 17) {
+             asyncStep = 18;
+             log('WKFOOBAR(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("WKFOOBAR", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 18) {
+             asyncStep = 19;
+             log('WKFOOBAR("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("SEARCH", "methods.cgi", true);
+             req.send("");
+           } else if (asyncStep == 19) {
+             asyncStep = 20;
+             log('SEARCH(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("SEARCH", "methods.cgi", true);
+             req.send(null);
+           } else if (asyncStep == 20) {
+             asyncStep = 21;
+             log('SEARCH(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             req.open("SEARCH", "methods.cgi", true);
+             req.send("123");
+           } else if (asyncStep == 21) {
+             log('SEARCH("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+             if (window.layoutTestController)
+               layoutTestController.notifyDone();
+           }
+        } else {
+           log("Error loading URL: status " + req.status);
+        }
+      }
+    }
+
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/xmlhttprequest/methods-expected.txt b/LayoutTests/http/tests/xmlhttprequest/methods-expected.txt
new file mode 100644 (file)
index 0000000..cd8e48f
--- /dev/null
@@ -0,0 +1,21 @@
+Tests for bug 3812 - GET and POST should not be the only HTTP methods implemented in XMLHttpRequest.
+
+GET(""): GET(undefined bytes), Content-Type: undefined
+GET(null): GET(undefined bytes), Content-Type: undefined
+GET("123"): GET(undefined bytes), Content-Type: undefined
+POST(""): POST(0 bytes), Content-Type: application/xml
+POST(null): POST(0 bytes), Content-Type: undefined
+POST("123"): POST(3 bytes), Content-Type: application/xml
+PUT(""): PUT(0 bytes), Content-Type: application/xml
+PUT(null): PUT(0 bytes), Content-Type: undefined
+PUT("123"): PUT(3 bytes), Content-Type: application/xml
+DELETE(""): DELETE(0 bytes), Content-Type: application/xml
+DELETE(null): DELETE(0 bytes), Content-Type: undefined
+DELETE("123"): DELETE(3 bytes), Content-Type: application/xml
+WKFOOBAR(""): WKFOOBAR(0 bytes), Content-Type: application/xml
+WKFOOBAR(null): WKFOOBAR(0 bytes), Content-Type: undefined
+WKFOOBAR("123"): WKFOOBAR(3 bytes), Content-Type: application/xml
+SEARCH(""): SEARCH(0 bytes), Content-Type: application/xml
+SEARCH(null): SEARCH(0 bytes), Content-Type: undefined
+SEARCH("123"): SEARCH(3 bytes), Content-Type: application/xml
+
diff --git a/LayoutTests/http/tests/xmlhttprequest/methods.cgi b/LayoutTests/http/tests/xmlhttprequest/methods.cgi
new file mode 100755 (executable)
index 0000000..4413ffe
--- /dev/null
@@ -0,0 +1,16 @@
+#!/usr/bin/perl -w
+
+print "Content-type: text/plain\n"; 
+print "Content-Length: 0\n";
+my $cl = $ENV{'CONTENT_LENGTH'};
+my $ct = $ENV{'CONTENT_TYPE'};
+my $method = $ENV{'REQUEST_METHOD'};
+if (defined $cl) {
+    print "REQLENGTH: $cl\n";
+}
+if (defined $ct) {
+    print "REQTYPE: $ct\n";
+}
+print "REQMETHOD: $method\n";
+
+print "\n";
diff --git a/LayoutTests/http/tests/xmlhttprequest/methods.html b/LayoutTests/http/tests/xmlhttprequest/methods.html
new file mode 100644 (file)
index 0000000..ef19f78
--- /dev/null
@@ -0,0 +1,107 @@
+<html>
+<body>
+<p>Tests for <a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=3812"> bug 3812</a> - 
+GET and POST should not be the only HTTP methods implemented in XMLHttpRequest.</p>
+<script>
+    if (window.layoutTestController)
+        layoutTestController.dumpAsText();
+    
+    var console_messages = document.createElement("ol");
+    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", "methods.cgi", false);
+    req.send("");
+    log('GET(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("GET", "methods.cgi", false);
+    req.send(null);
+    log('GET(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("GET", "methods.cgi", false);
+    req.send("123");
+    log('GET("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("POST", "methods.cgi", false);
+    req.send("");
+    log('POST(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("POST", "methods.cgi", false);
+    req.send(null);
+    log('POST(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("POST", "methods.cgi", false);
+    req.send("123");
+    log('POST("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("PUT", "methods.cgi", false);
+    req.send("");
+    log('PUT(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("PUT", "methods.cgi", false);
+    req.send(null);
+    log('PUT(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("PUT", "methods.cgi", false);
+    req.send("123");
+    log('PUT("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("DELETE", "methods.cgi", false);
+    req.send("");
+    log('DELETE(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("DELETE", "methods.cgi", false);
+    req.send(null);
+    log('DELETE(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("DELETE", "methods.cgi", false);
+    req.send("123");
+    log('DELETE("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+/*
+    req.open("HEAD", "methods.cgi", false);
+    req.send("");
+    log('HEAD(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("HEAD", "methods.cgi", false);
+    req.send(null);
+    log('HEAD(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("HEAD", "methods.cgi", false);
+    req.send("123");
+    log('HEAD("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+*/
+    req.open("WKFOOBAR", "methods.cgi", false);
+    req.send("");
+    log('WKFOOBAR(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("WKFOOBAR", "methods.cgi", false);
+    req.send(null);
+    log('WKFOOBAR(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("WKFOOBAR", "methods.cgi", false);
+    req.send("123");
+    log('WKFOOBAR("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("SEARCH", "methods.cgi", false);
+    req.send("");
+    log('SEARCH(""): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("SEARCH", "methods.cgi", false);
+    req.send(null);
+    log('SEARCH(null): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+    req.open("SEARCH", "methods.cgi", false);
+    req.send("123");
+    log('SEARCH("123"): ' + req.getResponseHeader("REQMETHOD") + "(" + req.getResponseHeader("REQLENGTH") + " bytes), Content-Type: " + req.getResponseHeader("REQTYPE"));
+
+</script>
+</body>
+</html>
index bee7f9df41c89b6ef13bc998164277622ff07c78..76880b33aaea9d149ad76047b2d2e280feb0d230 100644 (file)
@@ -1,3 +1,35 @@
+2006-03-01  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Darin.
+
+        - http://bugzilla.opendarwin.org/show_bug.cgi?id=3812
+          XMLHttpRequest: PUT, DELETE, HEAD and all other methods but POST actually do a GET.
+
+        HEAD is currently unimplemented because of what seems to be a bug in NSURLConnection,
+        and does a GET instead.
+
+        * kwq/KWQKJobClasses.h: Add a method parameter to TransferJob.
+        * kwq/KWQKJobClasses.mm:
+        (WebCore::TransferJobPrivate::TransferJobPrivate):
+        (WebCore::TransferJob::TransferJob):
+        (WebCore::TransferJob::method):
+        * bridge/mac/WebCoreFrameBridge.h: URL loading functions now take a method parameter.
+        * dom/xml_tokenizer.cpp:
+        (WebCore::openFunc):
+        * khtml/xsl/xslt_processorimpl.cpp:
+        (DOM::docLoaderFunc):
+        * kwq/KWQLoader.mm:
+        (KWQServeRequest):
+        (KWQServeSynchronousRequest):
+        * loader/loader.cpp:
+        (WebCore::Loader::servePendingRequests):
+        * page/Frame.cpp:
+        (WebCore::Frame::didOpenURL):
+        * xml/xmlhttprequest.cpp:
+        (WebCore::XMLHttpRequest::send): Honor the method passed in open().
+        * khtml/ecma/JSXMLHttpRequest.cpp:
+        (KJS::JSXMLHttpRequestProtoFunc::callAsFunction): Don't serialize null as "null".
+
 2006-03-01  Timothy Hatcher  <timothy@apple.com>
 
         Reviewed by Darin.
index c8e031491e73d8370ea5e8474a9c2e0237b5083d..e93f593aaadd71b3431dc66e0c188cc254aab41c 100644 (file)
@@ -535,11 +535,11 @@ typedef enum {
 - (BOOL)runBeforeUnloadConfirmPanelWithMessage:(NSString *)message;
 - (void)addMessageToConsole:(NSDictionary *)message;
 
-- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)loader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders;
-- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)loader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)data;
+- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)loader withMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders;
+- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)loader withMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)data;
 - (void)objectLoadedFromCacheWithURL:(NSURL *)URL response:(NSURLResponse *)response data:(NSData *)data;
 
-- (NSData *)syncLoadResourceWithURL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalNSURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode;
+- (NSData *)syncLoadResourceWithMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalNSURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode;
 
 - (BOOL)isReloading;
 - (time_t)expiresTimeForResponse:(NSURLResponse *)response;
index f342dd68c04b48bd2b0f0c8196315a8c10dbbb43..146efff53ca30cfd866b14063aab86915a70ec4e 100644 (file)
@@ -181,7 +181,7 @@ static void* openFunc(const char* uri)
         return &globalDescriptor;
 
     KURL finalURL;
-    TransferJob* job = new TransferJob(0, uri);
+    TransferJob* job = new TransferJob(0, "GET", uri);
     QString headers;
     ByteArray data = KWQServeSynchronousRequest(Cache::loader(), globalDocLoader, job, finalURL, headers);
     
index ee2acffef75d26e680e623f7ecb904f7bfbb40d8..b41752ac4f39726dce246e468868bbcd616ccff4 100644 (file)
@@ -222,8 +222,10 @@ JSValue* JSXMLHttpRequestProtoFunc::callAsFunction(ExecState *exec, JSObject* th
           body = doc->toString().qstring();
         } else {
           // converting certain values (like null) to object can set an exception
-          exec->clearException();
-          body = args[0]->toString(exec).domString();
+          if (exec->hadException())
+            exec->clearException();
+          else
+            body = args[0]->toString(exec).domString();
         }
       }
 
index 80c0c94b5a9e6d7fa37eaca446b6fe1751632066..323f11ad14b7946f5370821be1e3205da7497eed 100644 (file)
@@ -88,7 +88,7 @@ static xmlDocPtr docLoaderFunc(const xmlChar *uri,
             KURL url((const char*)base, (const char*)uri);
             xmlFree(base);
             KURL finalURL;
-            TransferJob* job = new TransferJob(0, url);
+            TransferJob* job = new TransferJob(0, "GET", url);
             QString headers;
             xmlGenericErrorFunc oldErrorFunc = xmlGenericError;
             void *oldErrorContext = xmlGenericErrorContext;
index 90a4a5b9d72b471f7675c1c4f58ca591ec0d965c..b036040bbf95fd220e84c3f4a5e843ded12241e0 100644 (file)
@@ -47,8 +47,8 @@ class TransferJobPrivate;
 
 class TransferJob {
 public:
-    TransferJob(TransferJobClient*, const KURL&);
-    TransferJob(TransferJobClient*, const KURL&, const FormData& postData);
+    TransferJob(TransferJobClient*, const String& method, const KURL&);
+    TransferJob(TransferJobClient*, const String& method, const KURL&, const FormData& postData);
     ~TransferJob();
 
     int error() const;
@@ -61,7 +61,7 @@ public:
     void kill();
 
     KURL url() const;
-    QString method() const;
+    String method() const;
     FormData postData() const;
 
 #if __APPLE__
index e4f3f9ba1782f9310d048df971812345b5f4f5d7..c9a41253c636d0bee471f47203a204193a880a68 100644 (file)
@@ -44,26 +44,26 @@ namespace WebCore {
 class TransferJobPrivate
 {
 public:
-    TransferJobPrivate(TransferJobClient* c, const KURL& u)
+    TransferJobPrivate(TransferJobClient* c, const String& method, const KURL& u)
         : client(c)
         , status(0)
         , metaData(KWQRetainNSRelease([[NSMutableDictionary alloc] initWithCapacity:17]))
        , URL(u)
        , loader(nil)
-       , method("GET")
+       , method(method)
        , response(nil)
         , assembledResponseHeaders(true)
         , retrievedCharset(true)
     {
     }
 
-    TransferJobPrivate(TransferJobClient* c, const KURL& u, const FormData& p)
+    TransferJobPrivate(TransferJobClient* c, const String& method, const KURL& u, const FormData& p)
         : client(c)
         , status(0)
         , metaData(KWQRetainNSRelease([[NSMutableDictionary alloc] initWithCapacity:17]))
        , URL(u)
        , loader(nil)
-       , method("POST")
+       , method(method)
        , postData(p)
        , response(nil)
        , assembledResponseHeaders(true)
@@ -84,7 +84,7 @@ public:
     NSMutableDictionary* metaData;
     KURL URL;
     KWQResourceLoader* loader;
-    QString method;
+    String method;
     FormData postData;
 
     NSURLResponse* response;
@@ -93,13 +93,13 @@ public:
     QString responseHeaders;
 };
 
-TransferJob::TransferJob(TransferJobClient* client, const KURL& url)
-    : d(new TransferJobPrivate(client, url))
+TransferJob::TransferJob(TransferJobClient* client, const String& method, const KURL& url)
+    : d(new TransferJobPrivate(client, method, url))
 {
 }
 
-TransferJob::TransferJob(TransferJobClient* client, const KURL& url, const FormData& postData)
-    : d(new TransferJobPrivate(client, url, postData))
+TransferJob::TransferJob(TransferJobClient* client, const String& method, const KURL& url, const FormData& postData)
+    : d(new TransferJobPrivate(client, method, url, postData))
 {
 }
 
@@ -211,7 +211,7 @@ FormData TransferJob::postData() const
     return d->postData;
 }
 
-QString TransferJob::method() const
+String TransferJob::method() const
 {
     return d->method;
 }
index 45b2752d57935198449886e7f1cd4c370bc402a3..365289e691a299a9a2d55faa0d0d5e30a35e891c 100644 (file)
@@ -131,11 +131,11 @@ bool KWQServeRequest(Loader *loader, DocLoader *docLoader, TransferJob *job)
         headerDict = [NSDictionary _webcore_dictionaryWithHeaderString:headerString.getNSString()];
     }
 
-    if (job->method() == "POST") {
-        handle = [bridge startLoadingResource:resourceLoader withURL:job->url().getNSURL() customHeaders:headerDict
+    if (job->postData().count() > 0) {
+        handle = [bridge startLoadingResource:resourceLoader withMethod:job->method() URL:job->url().getNSURL() customHeaders:headerDict
             postData:arrayFromFormData(job->postData())];
     } else {
-        handle = [bridge startLoadingResource:resourceLoader withURL:job->url().getNSURL() customHeaders:headerDict];
+        handle = [bridge startLoadingResource:resourceLoader withMethod:job->method() URL:job->url().getNSURL() customHeaders:headerDict];
     }
     [resourceLoader setHandle:handle];
     [resourceLoader release];
@@ -190,14 +190,13 @@ ByteArray KWQServeSynchronousRequest(Loader *loader, DocLoader *docLoader, Trans
     }
 
     NSArray *postData = nil;
-    if (job->method() == "POST") {
+    if (job->postData().count() > 0)
         postData = arrayFromFormData(job->postData());
-    }
 
     NSURL *finalNSURL = nil;
     NSDictionary *responseHeaderDict = nil;
     int statusCode = 0;
-    NSData *resultData = [bridge syncLoadResourceWithURL:job->url().getNSURL() customHeaders:headerDict postData:postData finalURL:&finalNSURL responseHeaders:&responseHeaderDict statusCode:&statusCode];
+    NSData *resultData = [bridge syncLoadResourceWithMethod:job->method() URL:job->url().getNSURL() customHeaders:headerDict postData:postData finalURL:&finalNSURL responseHeaders:&responseHeaderDict statusCode:&statusCode];
     [headerDict release];
     
     job->kill();
index 3bed93eb79aa9174fb415bf5519d85c6f48f9463..ec3ffe12893c18db0b3a53171260dc2940a3d40b 100644 (file)
@@ -93,7 +93,7 @@ void Loader::servePendingRequests()
   Request *req = m_requestsPending.take(0);
 
   KURL u(req->object->url().qstring());
-  TransferJob* job = new TransferJob(this, u);
+  TransferJob* job = new TransferJob(this, "GET", u);
   
   if (!req->object->accept().isEmpty())
       job->addMetaData("accept", req->object->accept());
index c29df7d19cabce2c537f845bbce1404983026a22..5580f3c3b0d4fd9756fe52c7e8cfec4c0cdf98a8 100644 (file)
@@ -225,10 +225,10 @@ bool Frame::didOpenURL(const KURL &url)
      d->m_cachePolicy = KIO::CC_Verify;
 
   if (args.doPost() && url.protocol().startsWith("http")) {
-      d->m_job = new TransferJob(this, url, args.postData);
+      d->m_job = new TransferJob(this, "POST", url, args.postData);
       d->m_job->addMetaData("content-type", args.contentType() );
   } else
-      d->m_job = new TransferJob(this, url);
+      d->m_job = new TransferJob(this, "GET", url);
 
   d->m_job->addMetaData(args.metaData());
 
index be418127ba6a2e9c6fe2d489f9800de502b8a1ca..35c0b1d2f05f4f661529883f1838746536a7c842 100644 (file)
@@ -240,7 +240,7 @@ void XMLHttpRequest::send(const DOMString& _body)
 
   aborted = false;
 
-  if (method.lower() == "post" && (url.protocol().lower() == "http" || url.protocol().lower() == "https") ) {
+  if (!_body.isNull() && method.lower() != "get" && method.lower() != "head" && (url.protocol().lower() == "http" || url.protocol().lower() == "https")) {
       QString contentType = getRequestHeader("Content-Type");
       QString charset;
       if (contentType.isEmpty())
@@ -255,10 +255,15 @@ void XMLHttpRequest::send(const DOMString& _body)
       if (!encoding.isValid())   // FIXME: report an error?
         encoding = TextEncoding(UTF8Encoding);
 
-      job = new TransferJob(async ? this : 0, url, encoding.fromUnicode(_body.qstring()));
+      job = new TransferJob(async ? this : 0, method, url, encoding.fromUnicode(_body.qstring()));
+  } else {
+     // HEAD requests just crash; see <rdar://4460899> and the commented out tests in http/tests/xmlhttprequest/methods.html.
+     if (method.lower() == "head")
+       method = "GET";
+
+     job = new TransferJob(async ? this : 0, method, url);
   }
-  else
-     job = new TransferJob(async ? this : 0, url);
+
   if (requestHeaders.length() > 0)
     job->addMetaData("customHTTPHeader", requestHeaders);
 
index 3b17413c1097688c14705088a5448b6e201c5934..5128de39e5101babc5a7d20c921b60f1094f4116 100644 (file)
@@ -1,3 +1,21 @@
+2006-03-01  Alexey Proskuryakov  <ap@nypop.com>
+
+        Reviewed by Darin.
+
+        - http://bugzilla.opendarwin.org/show_bug.cgi?id=3812
+          XMLHttpRequest: PUT, DELETE, HEAD and all other methods but POST actually do a GET.
+
+        All WebKit changes are to use the method parameter passed from WebCore.
+
+        * WebCoreSupport/WebFrameBridge.m:
+        (-[WebFrameBridge startLoadingResource:withMethod:URL:customHeaders:]):
+        (-[WebFrameBridge startLoadingResource:withMethod:URL:customHeaders:postData:]):
+        (-[WebFrameBridge syncLoadResourceWithMethod:URL:customHeaders:postData:finalURL:responseHeaders:statusCode:]):
+        * WebCoreSupport/WebSubresourceLoader.h:
+        * WebCoreSupport/WebSubresourceLoader.m:
+        (+[WebSubresourceLoader startLoadingResource:withMethod:URL:customHeaders:referrer:forDataSource:]):
+        (+[WebSubresourceLoader startLoadingResource:withMethod:URL:customHeaders:postData:referrer:forDataSource:]):
+
 2006-03-01  Timothy Hatcher  <timothy@apple.com>
 
         Reviewed by Darin.
index 09d391cde75c6e00caa87e0d13396cea9e2e322d..10ef2f79e35325e9583965a6f68509e7286e2ca5 100644 (file)
@@ -478,7 +478,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     [self addData:data];
 }
 
-- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders
+- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders
 {
     // If we are no longer attached to a WebView, this must be an attempted load from an
     // onUnload handler, so let's just block it.
@@ -491,13 +491,14 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     [self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer];
 
     return [WebSubresourceLoader startLoadingResource:resourceLoader
-                                              withURL:URL
+                                           withMethod:method
+                                                  URL:URL
                                         customHeaders:customHeaders
                                              referrer:(hideReferrer ? nil : [self referrer])
                                         forDataSource:[self dataSource]];
 }
 
-- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withURL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)postData
+- (id <WebCoreResourceHandle>)startLoadingResource:(id <WebCoreResourceLoader>)resourceLoader withMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)customHeaders postData:(NSArray *)postData
 {
     // If we are no longer attached to a WebView, this must be an attempted load from an
     // onUnload handler, so let's just block it.
@@ -510,8 +511,9 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     [self canLoadURL:URL fromReferrer:[self referrer] hideReferrer:&hideReferrer];
 
     return [WebSubresourceLoader startLoadingResource:resourceLoader
-                                              withURL:URL
-                                         customHeaders:customHeaders
+                                           withMethod:method 
+                                                  URL:URL
+                                        customHeaders:customHeaders
                                              postData:postData
                                              referrer:(hideReferrer ? nil : [self referrer])
                                         forDataSource:[self dataSource]];
@@ -528,7 +530,7 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     [request release];
 }
 
-- (NSData *)syncLoadResourceWithURL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
+- (NSData *)syncLoadResourceWithMethod:(NSString *)method URL:(NSURL *)URL customHeaders:(NSDictionary *)requestHeaders postData:(NSArray *)postData finalURL:(NSURL **)finalURL responseHeaders:(NSDictionary **)responseHeaderDict statusCode:(int *)statusCode
 {
     // Since this is a subresource, we can load any URL (we ignore the return value).
     // But we still want to know whether we should hide the referrer or not, so we call the canLoadURL method.
@@ -538,10 +540,9 @@ NSString *WebPluginContainerKey =   @"WebPluginContainer";
     NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:URL];
     [request setTimeoutInterval:10];
 
-    if (postData) {
-        [request setHTTPMethod:@"POST"];
+    [request setHTTPMethod:method];
+    if (postData)        
         webSetHTTPBody(request, postData);
-    }
 
     NSEnumerator *e = [requestHeaders keyEnumerator];
     NSString *key;
index 0db3a8be2be020e7af8562538477b3f7f835e278..4b87a80d8a2098f2ab86920bc31ac1d579022ea4 100644 (file)
 - (void)signalFinish;
 
 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
-                                       withURL:(NSURL *)URL 
+                                    withMethod:(NSString *)method
+                                           URL:(NSURL *)URL 
                                  customHeaders:(NSDictionary *)customHeaders
                                       referrer:(NSString *)referrer 
                                  forDataSource:(WebDataSource *)source;
 
 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
-                                       withURL:(NSURL *)URL 
+                                    withMethod:(NSString *)method
+                                           URL:(NSURL *)URL 
                                  customHeaders:(NSDictionary *)customHeaders
                                       postData:(NSArray *)postData 
                                       referrer:(NSString *)referrer 
index 20e2b10d80daf0384ead574f6f0333fe37cd0727..044e0bff419215557f4ef50f50e3a253b67e9cdf 100644 (file)
 }
 
 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
-                                      withURL:(NSURL *)URL
-                                customHeaders:(NSDictionary *)customHeaders
-                                     referrer:(NSString *)referrer
-                                forDataSource:(WebDataSource *)source
+                                    withMethod:(NSString *)method 
+                                           URL:(NSURL *)URL
+                                 customHeaders:(NSDictionary *)customHeaders
+                                      referrer:(NSString *)referrer
+                                 forDataSource:(WebDataSource *)source
 {
     NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
+    [newRequest setHTTPMethod:method];
+
     WebSubresourceLoader *loader = [self startLoadingResource:rLoader withRequest:newRequest customHeaders:customHeaders referrer:referrer forDataSource:source];
     [newRequest release];
 
 }
 
 + (WebSubresourceLoader *)startLoadingResource:(id <WebCoreResourceLoader>)rLoader
-                                      withURL:(NSURL *)URL
-                                customHeaders:(NSDictionary *)customHeaders
-                                     postData:(NSArray *)postData
-                                     referrer:(NSString *)referrer
-                                forDataSource:(WebDataSource *)source
+                                    withMethod:(NSString *)method 
+                                           URL:(NSURL *)URL
+                                 customHeaders:(NSDictionary *)customHeaders
+                                      postData:(NSArray *)postData
+                                      referrer:(NSString *)referrer
+                                 forDataSource:(WebDataSource *)source
 {
     NSMutableURLRequest *newRequest = [[NSMutableURLRequest alloc] initWithURL:URL];
 
-    [newRequest setHTTPMethod:@"POST"];
+    [newRequest setHTTPMethod:method];
     webSetHTTPBody(newRequest, postData);
 
     WebSubresourceLoader *loader = [self startLoadingResource:rLoader withRequest:newRequest customHeaders:customHeaders referrer:referrer forDataSource:source];