Zend_Xmlrpcでエラー

ふつーに使おうとしたらオペランドがどうこういわれた

$client = new Zend_XmlRpc_Client('http://example.com/api/xmlrpc');
$client->call('Hogehoge.entry');

とふつーに使おうとしたら

Fatal error: Unsupported operand types in /usr/local/php/lib/php/Zend/Http/Client/Adapter/Socket.php on line 303

とか、言われることがあった。
http://example.com/api/xmlrpcがContent-lengthを2回返すサーバーだったりすると言われる。
Zend/Http/Client/Adapter/Socket.phpの当該部分をみると

while ($left_to_read > 0) {
    $chunk = @fread($this->socket, $left_to_read);

    if ($chunk === false || strlen($chunk) === 0)
    {
        break;
    } else {
        $left_to_read -= strlen($chunk);
        $response .= $chunk;
    }

    // Break if the connection ended prematurely
    if (feof($this->socket)) break;
}

となっていて

$left_to_read -= strlen($chunk);

でこけてる。

$left_to_readは

$left_to_read = $headers['content-length'];

で、$headersは

$headers = Zend_Http_Response::extractHeaders($response);

で、$responseは

while (($line = @fgets($this->socket)) !== false) {
    $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
    if ($gotStatus) {
        $response .= $line;
        if (rtrim($line) === '') break;
    }
}

で、$this->socketは

$this->socket = @stream_socket_client($host . ':' . $port,
                                      $errno,
                                      $errstr,
                                      (int) $this->config['timeout'],
                                      $flags,
                                      $context);

Zend_Http_Response::extractHeaders($response);

で、そこのメソッドは

    /**
     * Extract the headers from a response string
     *
     * @param string $response_str
     * @return array
     */
    public static function extractHeaders($response_str)
    {
        $headers = array();
        
        // First, split body and headers
        $parts = preg_split('|(?:\r?\n){2}|m', $response_str, 2);
        if (! $parts[0]) return $headers;
        
        // Split headers part to lines
        $lines = explode("\n", $parts[0]);
        unset($parts);
        $last_header = null;

        foreach($lines as $line) {
            $line = trim($line, "\r\n");
            if ($line == "") break;

            if (preg_match("|^([\w-]+):\s+(.+)|", $line, $m)) {
                unset($last_header);
                $h_name = strtolower($m[1]);
                $h_value = $m[2];

                if (isset($headers[$h_name])) {
                    if (! is_array($headers[$h_name])) {
                        $headers[$h_name] = array($headers[$h_name]);
                    }

                    $headers[$h_name][] = $h_value;
                } else {
                    $headers[$h_name] = $h_value;
                }
                $last_header = $h_name;
            } elseif (preg_match("|^\s+(.+)$|", $line, $m) && $last_header !== null) {
                if (is_array($headers[$last_header])) {
                    end($headers[$last_header]);
                    $last_header_key = key($headers[$last_header]);
                    $headers[$last_header][$last_header_key] .= $m[1];
                } else {
                    $headers[$last_header] .= $m[1];
                }
            }
        }

        return $headers;
    }

なので

if (isset($headers[$h_name])) {
    if (! is_array($headers[$h_name])) {
        $headers[$h_name] = array($headers[$h_name]);
    }

    $headers[$h_name][] = $h_value;
} else {
    $headers[$h_name] = $h_value;
}

から、同じ名前のやつがきたら配列として取っておくようなので
content-lengthが2行あれば
返ってくる$header['content-length']はarrayで帰ってくる

そーすると、最初の

while ($left_to_read > 0) {
    $chunk = @fread($this->socket, $left_to_read);

    if ($chunk === false || strlen($chunk) === 0)
    {
        break;
    } else {
        $left_to_read -= strlen($chunk);
        $response .= $chunk;
    }

    // Break if the connection ended prematurely
    if (feof($this->socket)) break;
}

は、$left_to_read -= strlen($chunk);とあるから、配列で帰ってこないことが前提なようなので
そこでFatal error: Unsupported operand typesだといわれる。

HTTPの仕様的には

受ける方が、余計なのを無視する方が正しいのだと思っているので、Zend_Http_Responseがいけない子な気がしている。

で、結局

もう、XML_RPCはPEARの方がいいかなぁとか、鯖側のライブラリもとっつきやすそうだし、クライアント側も型の指定とかもできるから、結合段階では、逆に速そう。。