Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 1.4.4

Bug #3037 hang until socket close in an HTTP/1.1 request
Submitted: 2004-12-27 15:52 UTC
From: vdevaux at jetmultimedia dot fr Assigned: avb
Status: Closed Package: HTTP_Request
PHP Version: 4.3.7 OS: linux
Roadmaps: (Not assigned)    

 [2004-12-27 15:52 UTC] vdevaux at jetmultimedia dot fr
Description: ------------ in HTTP_Request version 1.2.3, in the function _readChunked; the readAll function does not return until the socket is closed: so will the _readChuncked function too, instead of returning when a 0 length chunk part is found. Reproduce code: --------------- Instead of if (0 == $this->_chunkLength) { $this->_sock->readAll(); // make this an eof() return ''; } I propose if (0 == $this->_chunkLength) { $this->_sock->readLine(); return ''; } It then will return as soon as possible without leaving characters to be read on the socket but without waiting for it to be closed.


 [2004-12-28 19:41 UTC] avb
I do not see the benefit of this change, since both Net_Socket::readAll() and HTTP_Response::process() (which calls _readChunked()) read the socket until eof. Did you test it?
 [2005-01-07 15:24 UTC] vdevaux at jetmultimedia dot fr
ok, sorry for the delay i was in kind of a hurry here at work. i check the whole package and see that i make in fact more modifications than i first thought: here is the readChuncked function in its whole: function _readChunked() { if (0 == $this->_chunkLength) { $line = $this->_sock->readLine(); if (preg_match('/^([0-9a-f]+)/i', $line, $matches)){ $this->_chunkLength = hexdec($matches[1]); if (0 == $this->_chunkLength) { $this->_sock->readLine();// readline instead of readAll return ''; } } else { // this else ... return ''; // ... clause is new } } $data = $this->_sock->read($this->_chunkLength); $this->_chunkLength -= strlen($data); if (0 == $this->_chunkLength) { $this->_sock->readLine(); // Trailing CRLF } return $data; } And here is the HTTP_Response::process function with comments on the changed lines: function process($saveBody = true) { do { $line = $this->_sock->readLine(); if (sscanf($line, 'HTTP/%s %s', $http_version, $returncode) != 2) { return PEAR::raiseError('Malformed response.'); } else { $this->_protocol = 'HTTP/' . $http_version; $this->_code = intval($returncode); } while ('' !== ($header = $this->_sock->readLine())) { $this->_processHeader($header); } } while (100 == $this->_code); $this->_notify('gotHeaders', $this->_headers); $chunked = isset($this->_headers['transfer-encoding']) && ('chunked' == $this->_headers['transfer-encoding']); $gzipped = isset($this->_headers['content-encoding']) && ('gzip' == $this->_headers['content-encoding']); $hasBody = false; if((!isset($this->_headers['content-length'])) || ( 0 != $this->_headers['content-length'])) { // this is new while (!$this->_sock->eof()) { if ($chunked) { $data = $this->_readChunked(); } else { $data = $this->_sock->read(4096); } if ('' != $data) { $hasBody = true; if ($saveBody || $gzipped) { $this->_body .= $data; } $this->_notify($gzipped? 'gzTick': 'tick', $data); } else { // this break is new too break; } } } if ($hasBody) { // Uncompress the body if needed if ($gzipped) { $this->_body = gzinflate(substr($this->_body, 10)); $this->_notify('gotBody', $this->_body); } else { $this->_notify('gotBody'); } } return true; } I test it (i use it in production environment). It works well and correct a problem found on a server (this problem happens only on this server and is perhaps related to the presence of packet with obnly a 0 chunked length in it). Apart from that, i would like to submit you a new feature for this package: could you set a private variable that contains the request string and a function to get it? I did it already like that: in the file Request.php line 200: var $_request =''; line 655: function getRequest() { return $this->_request; } line 800: $this->_request=$request; Don't hesitate to contact me.
 [2005-08-26 13:35 UTC] rouanelion at msn dot com
Hello, I thing i have found a little problem of path in the Request.php librairie because the Request.php need three librairies: require_once 'PEAR.php'; require_once 'Net/Socket.php'; require_once 'Net/URL.php'; and the problem is that the Socket.php need that too: require_once 'PEAR.php'; but if you put PEAR.php into Net directory with the Socket.php, i have this problem Fatal error: Cannot redeclare class pear in /var/www/ on line 103. So i think there is an error of PATH.(maybe i was wrong) Best regards rouanelion
 [2005-11-06 18:32 UTC] avb
Proposed change for HTTP_Response added to CVS. Thanks! As for keeping the request string, this can be implemented by subclassing HTTP_Request and overriding _buildRequest(), no sense adding it to the base package.