gpt4 book ai didi

php - Zend_Http_Client - 从 Stream 读取?

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:45:58 25 4
gpt4 key购买 nike

我想使用 Zend_Http_Client 访问新的 Twitter Stream API。问题是,对该网页 ( http://stream.twitter.com/1/statuses/sample.json ) 的 HTTP 请求从未完成但一直在加载。

所以即使我将 Zend_Http_Client 设置为 setStream(),我也无法获取它发出的信息。

这是我目前的逻辑:

    $httpClient = new Zend_Http_Client("http://stream.twitter.com/1/statuses/sample.json");
$httpClient->setAuth("username", "password");
$httpClient->setStream("/tmp/twitter_stream");

flush();
ob_flush();

$response = $httpClient->request("GET");

// Never get here... :(
Zend_Debug::dump($response);
flush();
ob_flush();

while(true)
{
echo fgets($response->getStream());
flush();
ob_flush();
}

现在,一旦我开始请求,我就永远不会进入 while 循环。 Zend Framework 所做的是,它写入一个文件。

我之所以要使用 Zend_Http_Client 是因为我以后必须使用 OAuth 访问该 Stream API,而 Zend_Oauth 依赖于 Zend_Http_Client。

如有任何帮助,我们将不胜感激。

最佳答案

据我所知,目前唯一可能的方法是扩展 Zend_Http_Client_Adapter_Socket,从旧的 Zend_Client_Http_Adapter_Socket 复制 write 方法并将您的自定义逻辑插入 do...while 循环(参见//CUSTOM LOGIC此处在方法的末尾评论):

<?php

class App_Http_Client_Adapter_Socket extends Zend_Http_Client_Adapter_Socket
{

/**
* Read response from server
*
* @return string
*/
public function read()
{
// First, read headers only
$response = '';
$gotStatus = false;
$stream = !empty($this->config['stream']);

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

$this->_checkSocketReadTimeout();

$statusCode = Zend_Http_Response::extractCode($response);

// Handle 100 and 101 responses internally by restarting the read again
if ($statusCode == 100 || $statusCode == 101)
return $this->read();

// Check headers to see what kind of connection / transfer encoding we have
$headers = Zend_Http_Response::extractHeaders($response);

/**
* Responses to HEAD requests and 204 or 304 responses are not expected
* to have a body - stop reading here
*/
if ($statusCode == 304 || $statusCode == 204 ||
$this->method == Zend_Http_Client::HEAD)
{

// Close the connection if requested to do so by the server
if (isset($headers['connection']) && $headers['connection'] == 'close')
{
$this->close();
}
return $response;
}

// If we got a 'transfer-encoding: chunked' header
if (isset($headers['transfer-encoding']))
{

if (strtolower($headers['transfer-encoding']) == 'chunked')
{

do
{
$line = @fgets($this->socket);
$this->_checkSocketReadTimeout();

$chunk = $line;

// Figure out the next chunk size
$chunksize = trim($line);
if (!ctype_xdigit($chunksize))
{
$this->close();
require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Invalid chunk size "' .
$chunksize . '" unable to read chunked body');
}

// Convert the hexadecimal value to plain integer
$chunksize = hexdec($chunksize);

// Read next chunk
$read_to = ftell($this->socket) + $chunksize;

do
{
$current_pos = ftell($this->socket);
if ($current_pos >= $read_to)
break;

if ($this->out_stream)
{
if (stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0)
{
$this->_checkSocketReadTimeout();
break;
}
}
else
{
$line = @fread($this->socket, $read_to - $current_pos);
if ($line === false || strlen($line) === 0)
{
$this->_checkSocketReadTimeout();
break;
}
$chunk .= $line;
}
}
while (!feof($this->socket));

$chunk .= @ fgets($this->socket);
$this->_checkSocketReadTimeout();

if (!$this->out_stream)
{
$response .= $chunk;
}
}
while ($chunksize > 0);
}
else
{
$this->close();
require_once 'Zend/Http/Client/Adapter/Exception.php';
throw new Zend_Http_Client_Adapter_Exception('Cannot handle "' .
$headers['transfer-encoding'] . '" transfer encoding');
}

// We automatically decode chunked-messages when writing to a stream
// this means we have to disallow the Zend_Http_Response to do it again
if ($this->out_stream)
{
$response = str_ireplace("Transfer-Encoding: chunked\r\n", '', $response);
}
// Else, if we got the content-length header, read this number of bytes
}
elseif (isset($headers['content-length']))
{

// If we got more than one Content-Length header (see ZF-9404) use
// the last value sent
if (is_array($headers['content-length']))
{
$contentLength = $headers['content-length'][count($headers['content-length']) - 1];
}
else
{
$contentLength = $headers['content-length'];
}

$current_pos = ftell($this->socket);
$chunk = '';

for ($read_to = $current_pos + $contentLength; $read_to > $current_pos; $current_pos = ftell($this->socket))
{

if ($this->out_stream)
{
if (@stream_copy_to_stream($this->socket, $this->out_stream, $read_to - $current_pos) == 0)
{
$this->_checkSocketReadTimeout();
break;
}
}
else
{
$chunk = @fread($this->socket, $read_to - $current_pos);
if ($chunk === false || strlen($chunk) === 0)
{
$this->_checkSocketReadTimeout();
break;
}

$response .= $chunk;
}

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

// Fallback: just read the response until EOF
} else
{

do
{
if ($this->out_stream)
{
if (@stream_copy_to_stream($this->socket, $this->out_stream) == 0)
{
$this->_checkSocketReadTimeout();
break;
}
}
else
{
$buff = @fread($this->socket, 8192);
if ($buff === false || strlen($buff) === 0)
{
$this->_checkSocketReadTimeout();
break;
}
else
{
$response .= $buff;
}

// CUSTOM LOGIC HERE!!
echo $response;
flush();
ob_flush();
}
}
while (feof($this->socket) === false);

$this->close();
}

// Close the connection if requested to do so by the server
if (isset($headers['connection']) && $headers['connection'] == 'close')
{
$this->close();
}

return $response;
}
}

仍然非常欢迎任何其他建议,因为我觉得这更像是一种 hack 而不是有效的解决方案。

关于php - Zend_Http_Client - 从 Stream 读取?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3457015/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com