Fixed bug #69313
authorMichael Wallner <mike@php.net>
Fri, 27 Mar 2015 09:13:40 +0000 (10:13 +0100)
committerMichael Wallner <mike@php.net>
Fri, 27 Mar 2015 09:15:59 +0000 (10:15 +0100)
package.xml
php_http_client_curl.c
tests/bug69313.phpt [new file with mode: 0644]

index 99b9abe..b8d4f9a 100644 (file)
@@ -47,6 +47,7 @@ http://dev.iworks.at/ext-http/lcov/ext/http/
  <license>BSD, revised</license>
  <notes><![CDATA[
 * Fixed bug 69076 (http\Url throws Exception on empty querystring) (p at wspnr dot com)
+* Fixed bug 69313 (http\Client doesn't send GET body)
 + Added libidn2 and UIDNA as fallbacks for IDN support
 - Deferred warnings/exceptions of the client, so callbacks for the currently failing requests will still be called
 ]]></notes>
index 252d818..43a9337 100644 (file)
@@ -1908,35 +1908,6 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_prepare(php_http_client_cur
        php_http_url_to_string(PHP_HTTP_INFO(msg).request.url, &storage->url, NULL, 1);
        curl_easy_setopt(curl->handle, CURLOPT_URL, storage->url);
 
-       /* request method */
-       switch (php_http_select_str(PHP_HTTP_INFO(msg).request.method, 4, "GET", "HEAD", "POST", "PUT")) {
-               case 0:
-                       curl_easy_setopt(curl->handle, CURLOPT_HTTPGET, 1L);
-                       break;
-
-               case 1:
-                       curl_easy_setopt(curl->handle, CURLOPT_NOBODY, 1L);
-                       break;
-
-               case 2:
-                       curl_easy_setopt(curl->handle, CURLOPT_POST, 1L);
-                       break;
-
-               case 3:
-                       curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1L);
-                       break;
-
-               default: {
-                       if (PHP_HTTP_INFO(msg).request.method) {
-                               curl_easy_setopt(curl->handle, CURLOPT_CUSTOMREQUEST, PHP_HTTP_INFO(msg).request.method);
-                       } else {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot use empty request method");
-                               return FAILURE;
-                       }
-                       break;
-               }
-       }
-
        /* apply options */
        php_http_options_apply(&php_http_curle_options, enqueue->options, curl);
 
@@ -1988,6 +1959,7 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_prepare(php_http_client_cur
                curl_easy_setopt(curl->handle, CURLOPT_READDATA, msg->body);
                curl_easy_setopt(curl->handle, CURLOPT_INFILESIZE, body_size);
                curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, body_size);
+               curl_easy_setopt(curl->handle, CURLOPT_POST, 1L);
        } else {
                curl_easy_setopt(curl->handle, CURLOPT_SEEKDATA, NULL);
                curl_easy_setopt(curl->handle, CURLOPT_READDATA, NULL);
@@ -1995,6 +1967,29 @@ static ZEND_RESULT_CODE php_http_client_curl_handler_prepare(php_http_client_cur
                curl_easy_setopt(curl->handle, CURLOPT_POSTFIELDSIZE, 0L);
        }
 
+       /*
+        * Always use CUSTOMREQUEST, else curl won't send any request body for GET etc.
+        * See e.g. bug #69313.
+        *
+        * Here's what curl does:
+        * - CURLOPT_HTTPGET: ignore request body
+        * - CURLOPT_UPLOAD: set "Expect: 100-continue" header
+        * - CURLOPT_POST: set "Content-Type: application/x-www-form-urlencoded" header
+        * Now select the least bad.
+        *
+        * See also https://tools.ietf.org/html/rfc7231#section-5.1.1
+        */
+       if (PHP_HTTP_INFO(msg).request.method) {
+               if (!strcasecmp("PUT", PHP_HTTP_INFO(msg).request.method)) {
+                       curl_easy_setopt(curl->handle, CURLOPT_UPLOAD, 1L);
+               } else {
+                       curl_easy_setopt(curl->handle, CURLOPT_CUSTOMREQUEST, PHP_HTTP_INFO(msg).request.method);
+               }
+       } else {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot use empty request method");
+               return FAILURE;
+       }
+
        return SUCCESS;
 }
 
diff --git a/tests/bug69313.phpt b/tests/bug69313.phpt
new file mode 100644 (file)
index 0000000..824918c
--- /dev/null
@@ -0,0 +1,46 @@
+--TEST--
+Bug #69313 (http\Client doesn't send GET body)
+--SKIPIF--
+<?php
+include "./skipif.inc";
+skip_client_test();
+?>
+--FILE--
+<?php
+
+
+include "helper/server.inc";
+
+echo "Test\n";
+
+server("proxy.inc", function($port, $stdin, $stdout, $stderr) {
+       $request = new http\Client\Request("GET", "http://localhost:$port/");
+       $request->setHeader("Content-Type", "text/plain");
+       $request->getBody()->append("foo");
+       $client = new http\Client();
+       $client->enqueue($request);
+       $client->send();
+       echo $client->getResponse();
+});
+
+?>
+
+Done
+--EXPECTF--
+Test
+HTTP/1.1 200 OK
+Accept-Ranges: bytes
+Etag: "%s"
+X-Original-Transfer-Encoding: chunked
+Content-Length: %d
+
+GET / HTTP/1.1
+User-Agent: %s
+Host: localhost:%d
+Accept: */*
+Content-Type: text/plain
+Content-Length: 3
+X-Original-Content-Length: 3
+
+foo
+Done