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

时间:2010-07-20 11:49:12

标签: php http java-me centos lighttpd

我有两个网站:一个使用Lighttpd和PHP,第二个使用Apache,这两个网站都没有正确处理分块传输编码。

我从我的手机J2ME发送此请求,并且无法将此传输类型更改为任何其他类型。

所以我唯一的办法就是以其他方式处理分块传输已编码的请求。任何解决方案都会很好,只要我可以在我的CentOS服务器上启用它,我可以安装并更改所有必要的东西。

所以我的问题是:如何在服务器端正确处理分块编码请求?

1 个答案:

答案 0 :(得分:5)

编辑: 您运行的是哪个版本的PHP / Apache / LightHTTP?由于之前PHP中有this bug,但它似乎已经消失了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
?>