HTTP协议之Transfer-Encoding

发表于:2018-09-07 18:26:05,已有843次阅读

说明

HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Date: Fri, 07 Sep 2018 10:17:06 GMT
Content-Type: text/html;charset=UTF-8
Transfer-Encoding: chunked
Connection: close

Transfer-Encoding: chunked说明是分块传输编码

分块传输编码(Chunked transfer encoding)是超文本传输协议(HTTP)中的一种数据传输机制,允许HTTP由网页服务器发送给客户端应用( 通常是网页浏览器)的数据可以分成多个部分。分块传输编码只在HTTP协议1.1版本(HTTP/1.1)中提供。

格式

chunked_format
图片来源:https://my.oschina.net/ososchina/blog/666761

伪代码

length := 0  //  用来记录解码后的数据体长度
read chunk-size, chunk-extension (if any) and CRLF  //  第一次读取块大小
while (chunk-size > 0) {  //  一直循环,直到读取的块大小为0
    read chunk-data and CRLF   // 读取块数据体,以回车结束
    append chunk-data to entity-body  // 添加块数据体到解码后实体数据
    length := length + chunk-size   //  更新解码后的实体长度
    read chunk-size and CRLF    //  读取新的块大小
}
read entity-header   //  以下代码读取全部的头标记,chunked算法只看上面
while (entity-header not empty) {
    append entity-header to existing header fields
    read entity-header
}
Content-Length := length    //  头标记中添加内容长度
Remove "chunked" from Transfer-Encoding   //  头标记中移除Transfer-Encoding

直接PHP翻译

使用的两个方法:
string substr ( string $string , int $start [, int $length ] ): 截取字符串
int stripos ( string $haystack , mixed $needle [, int $offset = 0 ] ): 查找子串位置

function unchunk($chunked) {
    $pos = 0;
    $unchunk = '';
    $CRLF = "\r\n";
    $length = 0;  //  用来记录解码后的数据体长度
    // 第一次读取块大小:read chunk-size, chunk-extension (if any) and CRLF
    echo $chunked.PHP_EOL;
    $pos = stripos($chunked, $CRLF);
    echo ">>" . $pos . PHP_EOL;
    $chunk_size = hexdec(substr($chunked, 0, $pos));  // 十六进制传十进制
    echo "HEX: " . substr($chunked, 0, $pos) . " DEC: " . $chunk_size . PHP_EOL;

    while($chunk_size > 0) { // 一直循环,直到读取的块大小为0
        $pos = $pos + strlen($CRLF);   // 跳过CRLF分隔符
        $unchunk .= substr($chunked, $pos, $chunk_size);  // 读取块数据体,以回车结束

        $length = $length + $chunk_size; // 更新解码后的实体长度

        $pos = $pos + $chunk_size + strlen($CRLF);   // 读取新的块大小, 跳过CRLF分隔符
        $idx = stripos($chunked, $CRLF, $pos);
        echo ">>" . $idx . PHP_EOL;
        $chunk_size = hexdec(substr($chunked, $pos, $idx - $pos));
        echo "HEX: " . substr($chunked, $pos, $idx - $pos) . " DEC: " . $chunk_size . PHP_EOL;
        $pos = $idx;
    }
    return $unchunk;
}

最后:优化

function unchunkClear($chunked) {
    $idx = 0;    // start
    $pos = 0;    // end
    $unchunk = '';
    $CRLF = "\r\n";
    $CRLFLEN = 2;
    $pos = stripos($chunked, $CRLF, $idx);
    $chunk_size = hexdec(substr($chunked, $idx, $pos - $idx));
    while($chunk_size > 0) {
        $idx = $pos + $CRLFLEN;
        $unchunk .= substr($chunked, $idx, $chunk_size);

        $idx = $idx + $chunk_size + $CRLFLEN;
        $pos = stripos($chunked, $CRLF, $idx);
        $chunk_size = hexdec(substr($chunked, $idx, $pos - $idx));
    }
    return $unchunk;
}

参考

分块传输编码
HTTP chunked编码数据流解析算法
PHP解码chunked编码的数据

分享到:

扫一扫,用手机观看!

用微信扫描还可以

分享至好友和朋友圈

二维码分享
评论

暂无评论

您还可输入120个字