如何正确处理分块编码请求?

3
我有两个网站:一个是用Lighttpd和PHP,另一个是用Apache,但它们都无法正确处理分块传输编码。
我从我的移动设备J2ME发送此请求,没有可能将此传输类型更改为其他类型。
所以,我唯一的选择是以其他方式处理分块传输编码请求。只要我能在我的CentOS服务器上启用并安装必要的内容,任何解决方案都可以。
因此,我的问题是:如何在服务器端正确处理分块编码请求?
1个回答

6

编辑: 你正在运行哪个版本的PHP / Apache / LightHTTP?因为之前有这个错误在PHP中出现过,但似乎已经在5.2.13和5.3.2中消失了。

如果上面的链接没有帮助,我想知道PHP确切看到了什么,您能否将此放入您的api并发布结果?(当然要进行编辑)。

$input = file_get_contents('php://input');
$stdin = file_get_contents('php://stdin');

print "FILES: ";
print_r($_FILES);

print("<br>POST: ");
print_r($_POST);

print("<br>input: ".$input);
print("<br>stdin: ".$stdin);
die;

这样我们可以看到PHP看到了什么,如果它没有解码分块编码,那么我们可以手动解码它。
编辑完毕。(为了其他人的参考而保留以下内容)
我假设这是你之前问题的跟进。并且我假设你正在从PHP读取流?
我写了这个几年前,它读取一个分块编码流,然后您可以对输出进行任何操作。如果是大文件,不要将其读入字符串中,而是写入文件。
<?php
define('CRLF', "\r\n");
define('BUFFER_LENGTH', 8192);
$headers = '';
$body = '';
$length = 0;

$fp = fsockopen($host, $port, $errno, $errstr, $timeout);

// get headers FIRST
do
{
    // use fgets() not fread(), fgets stops reading at first newline
    // or buffer which ever one is reached first
    $data = fgets($fp, BUFFER_LENGTH);
    // a sincle CRLF indicates end of headers
    if ($data === false || $data == CRLF || feof($fp)) {
        // break BEFORE OUTPUT
        break;
    }
    $headers .= $data;
}
while (true);
// end of headers

// read from chunked stream
// loop though the stream
do
{
    // NOTE: for chunked encoding to work properly make sure
    // there is NOTHING (besides newlines) before the first hexlength

    // get the line which has the length of this chunk (use fgets here)
    $line = fgets($fp, BUFFER_LENGTH);

    // if it's only a newline this normally means it's read
    // the total amount of data requested minus the newline
    // continue to next loop to make sure we're done
    if ($line == CRLF) {
        continue;
    }

    // the length of the block is sent in hex decode it then loop through
    // that much data get the length
    // NOTE: hexdec() ignores all non hexadecimal chars it finds
    $length = hexdec($line);

    if (!is_int($length)) {
        trigger_error('Most likely not chunked encoding', E_USER_ERROR);
    }

    // zero is sent when at the end of the chunks
    // or the end of the stream or error
    if ($line === false || $length < 1 || feof($fp)) {
        // break out of the streams loop
        break;
    }

    // loop though the chunk
    do
    {
        // read $length amount of data
        // (use fread here)
        $data = fread($fp, $length);

        // remove the amount received from the total length on the next loop
        // it'll attempt to read that much less data
        $length -= strlen($data);

        // PRINT out directly
        #print $data;
        #flush();
        // you could also save it directly to a file here

        // store in string for later use
        $body .= $data;

        // zero or less or end of connection break
        if ($length <= 0 || feof($fp))
        {
            // break out of the chunk loop
            break;
        }
    }
    while (true);
    // end of chunk loop
}
while (true);
// end of stream loop

// $body and $headers should contain your stream data
?>

我不从PHP读取流,但我的PHP脚本是通过分块POST调用调用的。如何读取此POST调用的流?你知道吗? - Tom Smykowski
所以J2ME正在调用您的PHP脚本,并期望分块编码输出,而apache和lighthttpd没有正确发送分块编码?从我的经验来看,您的php脚本必须以分块编码块的形式写出其数据。
  1. 调用api
  2. 处理结果
  3. 启动输出缓冲区
  4. 在缓冲区中收集错误或有效数据
  5. 处理缓冲区并转换为CE
  6. 发送正确的标头
  7. 发送分块编码数据
我没有任何已构建的代码,您可能可以在网上找到一些?如果没有,创建一个类也不难。
- Viper_Sb
看起来是这样的:J2ME向Apache或Lighttpd发送分块编码,但这两个服务器都无法正确接收此请求-它们只获取第一个块并且不读取更多。 - Tom Smykowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接