]> granicus.if.org Git - php/commitdiff
Fix #70361: HTTP stream wrapper doesn't close keep-alive connections
authorNiklas Keller <me@kelunik.com>
Tue, 25 Aug 2015 18:07:20 +0000 (20:07 +0200)
committerBob Weinand <bobwei9@hotmail.com>
Fri, 4 Sep 2015 14:29:35 +0000 (16:29 +0200)
NEWS
ext/standard/http_fopen_wrapper.c
ext/standard/tests/http/bug38802.phpt
ext/standard/tests/http/bug48929.phpt
ext/standard/tests/http/bug53198.phpt
ext/standard/tests/http/bug61548.phpt
ext/standard/tests/http/bug65634.phpt
ext/standard/tests/http/bug67430.phpt
ext/standard/tests/http/ignore_errors.phpt

diff --git a/NEWS b/NEWS
index 01c68a81f90e17640cdc2172f2909597c902d72a..4dcd8825d7a6c8cb969a6090ace42497afbf6399 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -11,7 +11,7 @@ PHP                                                                        NEWS
     DH key resource). (Jakub Zelenka)
 
 - PDO:
-  - Fixed bug #70389 (PDO constructor changes unrelated variables). (Laruence)
+  . Fixed bug #70389 (PDO constructor changes unrelated variables). (Laruence)
 
 - Phpdbg:
   . Fix phpdbg_break_next() sometimes not breaking. (Bob)
@@ -19,6 +19,10 @@ PHP                                                                        NEWS
 - Standard:
   . Fixed bug #67131 (setcookie() conditional for empty values not met). (cmb)
 
+- Streams:
+  . Fixed bug #70361 (HTTP stream wrapper doesn't close keep-alive connections).
+    (Niklas Keller)
+
 03 Sep 2015, PHP 5.6.13
 
 - Core:
index 25c83a8e1475b67d25dc936b09a5eefa38bd18d2..ce2a059ca4285965aca0ecf02e26f767414dc4a6 100644 (file)
@@ -576,13 +576,13 @@ finish:
                }
        }
 
-       /* Send a Connection: close header when using HTTP 1.1 or later to avoid
-        * hanging when the server interprets the RFC literally and establishes a
-        * keep-alive connection, unless the user specifically requests something
-        * else by specifying a Connection header in the context options. */
-       if (protocol_version &&
-           ((have_header & HTTP_HEADER_CONNECTION) == 0) &&
-           (strncmp(protocol_version, "1.0", MIN(protocol_version_len, 3)) > 0)) {
+       /* Send a Connection: close header to avoid hanging when the server
+        * interprets the RFC literally and establishes a keep-alive connection,
+        * unless the user specifically requests something else by specifying a
+        * Connection header in the context options. Send that header even for
+        * HTTP/1.0 to avoid issues when the server respond with a HTTP/1.1
+        * keep-alive response, which is the preferred response type. */
+       if ((have_header & HTTP_HEADER_CONNECTION) == 0) {
                php_stream_write_string(stream, "Connection: close\r\n");
        }
 
index 73b41183ae9db1260afe4b1ec46c0348be749a0a..5e9fd10273565f398bfd2f92c86453716a04f013 100644 (file)
@@ -86,44 +86,52 @@ array(7) {
   string(15) "HTTP/1.0 200 OK"
 }
 string(5) "done."
-string(195) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 GET /foo/bar2 HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 GET /foo/bar3 HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 GET /foo/bar4 HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: fail after 2 redirections --
 
 Warning: fopen(http://127.0.0.1:12342/foo/bar): failed to open stream: Redirection limit reached, aborting in %s
 bool(false)
-string(97) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 GET /foo/bar2 HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: fail at first redirection --
 
 Warning: fopen(http://127.0.0.1:12342/foo/bar): failed to open stream: Redirection limit reached, aborting in %s
 bool(false)
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: fail at first redirection (2) --
 
 Warning: fopen(http://127.0.0.1:12342/foo/bar): failed to open stream: Redirection limit reached, aborting in %s
 bool(false)
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: return at first redirection --
@@ -135,8 +143,9 @@ array(2) {
   string(41) "Location: http://127.0.0.1:12342/foo/bar2"
 }
 string(1) "1"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: return at first redirection (2) --
@@ -148,8 +157,9 @@ array(2) {
   string(41) "Location: http://127.0.0.1:12342/foo/bar2"
 }
 string(1) "1"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: return at second redirection --
@@ -165,10 +175,12 @@ array(4) {
   string(41) "Location: http://127.0.0.1:12342/foo/bar3"
 }
 string(0) ""
-string(97) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 GET /foo/bar2 HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
index 2d1e45917a218cad824c5801ef092c6aa7aa8fdd..b31ed292befad42290e63f32abec3e23d7061eb3 100644 (file)
@@ -39,18 +39,20 @@ echo "-- Test: requests with 'header' as string --\n";
 do_test(array('header' => "X-Foo: bar\r\nContent-Type: text/plain", 'method' => 'POST', 'content' => 'ohai'));
 
 ?>
---EXPECT--
+--EXPECTF--
 -- Test: requests with 'header' as array --
-string(103) "POST / HTTP/1.0
+string(%d) "POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 Content-Length: 4
 X-Foo: bar
 Content-Type: text/plain
 
 ohai"
 -- Test: requests with 'header' as string --
-string(103) "POST / HTTP/1.0
+string(%d) "POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 Content-Length: 4
 X-Foo: bar
 Content-Type: text/plain
index 3c640fa9c8234f0430a100ab4603d08a80c660e8..2585c3df6e2e5438141ea2df87f449ea3ded41d4 100644 (file)
@@ -41,17 +41,18 @@ ini_set('from', 'junk@junk.com');
 do_test();
 
 ?>
---EXPECT--
+--EXPECTF--
 -- Test: leave default --
-string(63) "GET / HTTP/1.0
+string(%d) "GET / HTTP/1.0
 From: teste@teste.pt
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: after ini_set --
-string(62) "GET / HTTP/1.0
+string(%d) "GET / HTTP/1.0
 From: junk@junk.com
 Host: 127.0.0.1:12342
+Connection: close
 
 "
-
index 138b15a338c063ebd3c55338a86e4f9f78fc05f4..38b2bbf08675c40eb606b746a4b08d9e44bd1de5 100644 (file)
@@ -44,30 +44,35 @@ Done
 --EXPECT--
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 Content-type: text/plain
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 
 
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 Content-type: text/plain
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 
 
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 Content-type: text/plain
@@ -75,34 +80,40 @@ Third:
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 Third:
 
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Content-type:text/plain
 Second:2
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Content-type:text/plain
 Second:2
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Content-type:text/plain
 Second:2
@@ -110,9 +121,9 @@ Third:
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 First:1
 Second:2
 Third:
 
 Done
-
index 8f358cc6cfc84b7f60cd75ea762256a9c9a967aa..2d2b13989e541de704e09acb5b4bf3fe4a5ce009 100644 (file)
@@ -53,6 +53,7 @@ do_test('1.1', 'keep-alive');
 HTTP/1.0, default behaviour:
 GET / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 HTTP/1.0, connection: close:
 GET / HTTP/1.0
@@ -78,4 +79,3 @@ HTTP/1.1, connection: keep-alive:
 GET / HTTP/1.1
 Host: 127.0.0.1:12342
 Connection: keep-alive
-
index d4474fdf5d270a16684826d7d0cf5b21789fcc2e..a563951cd8c449425f77491edc6e6063c34aaff5 100644 (file)
@@ -39,11 +39,14 @@ Done
 --EXPECT--
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 GET /foo HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 POST / HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 Done
index ab5421890bccf3190a61957a4f660a66496b1bba..54a0073b5e82c99ad433fc8c3a35421070b2f083 100644 (file)
@@ -27,7 +27,7 @@ function do_test($context_options) {
                if ($fd) {
                        $meta_data = stream_get_meta_data($fd);
                        var_dump($meta_data['wrapper_data']);
-       
+
                        var_dump(stream_get_contents($fd));
                }
 
@@ -62,16 +62,18 @@ array(2) {
   string(10) "X-Foo: bar"
 }
 string(1) "1"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 
 Warning: fopen(http://127.0.0.1:12342/foo/bar): failed to open stream: HTTP request failed! HTTP/1.0 404 Not found
  in %s on line %d
 bool(false)
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: requests with ignore_errors --
@@ -83,8 +85,9 @@ array(2) {
   string(10) "X-Foo: bar"
 }
 string(1) "1"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 resource(%d) of type (stream)
@@ -95,8 +98,9 @@ array(2) {
   string(10) "X-bar: baz"
 }
 string(1) "2"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 -- Test: requests with ignore_errors (2) --
@@ -108,8 +112,9 @@ array(2) {
   string(10) "X-Foo: bar"
 }
 string(1) "1"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "
 resource(%d) of type (stream)
@@ -120,7 +125,8 @@ array(2) {
   string(10) "X-bar: baz"
 }
 string(1) "2"
-string(48) "GET /foo/bar HTTP/1.0
+string(%d) "GET /foo/bar HTTP/1.0
 Host: 127.0.0.1:12342
+Connection: close
 
 "