Apache Chunked

Ce fut long, ténébreux… Un stagiaire utilisant un proxy PHP que j’ai codé (pour des requête Ajax distantes) avait parfois des retours “cassés”. Le contenu était bien là, mais commençait souvent par un code du genre “356e”. Le contenu de la réponse était bien correcte, puis suivait un “0” (zéro)…

Je pensais que mon ami le stagiaire avait placé des caractères spéciaux… D’ailleurs il n’utilisait pas UTF-8 (oreille gauche tirée) et laissait de temps en temps des lignes vierges en fin de script (oreille droite tirée).

Mais ce ne fut pas de sa faute… le proxy fonctionnait convenablement et la solution a été trouvé en regardant les entêtes de retour que Apache me donnait. Lorsque ces “codes” bizarres apparaissaient, il y avait une directive dans l’entête: Transfer-Encoding: chunked.

Un petit tour dans les doc Apache, et me voilà avec cette phrase magnifique:\\ //Get Body Chunk//\\ //The container asks for more data from the request (If the body was too large to fit in the first packet sent over or when the request is chuncked). The server will send a body packet back with an amount of data which is the minimum of the request_length, the maximum send body size (8186 (8 Kbytes - 6)), and the number of bytes actually left to send from the request body.//\
//If there is no more data in the body (i.e. the servlet container is trying to read past the end of the body), the server will send back an empty packet, which is a body packet with a payload length of 0. (0x12,0x34,0x00,0x00)//

Voilà donc le soucis :) La réponse renvoyée par Apache est encodée puisque trop longue ! J’ai donc trouvé la solution sur le script http://www.milw0rm.com/exploits/6053:

` function unchunk($data) { $dsize = 1; $offset = 0;

while($dsize>0){ $hsize_size = strpos($data, “\r\n”, $offset) - $offset;
$dsize = hexdec(substr($data, $offset, $hsize_size));

  //Remove $hsize\r\n from $data
  $data = substr($data, 0, $offset) . substr($data, ($offset + $hsize_size + 2) );
  $offset += $dsize;

  //Remove the \r\n before the next $hsize
  $data = substr($data, 0, $offset) . substr($data, ($offset+2) );

}
return $data; } `

A n’effectué que si vous trouvé le transfert Encoding à chunked, voici l’expression de test que je fais de mon coté:

//... $header est l'entête envoyé à Apache... à vous de la créer $fp = fsockopen($this->host,80) or die('ERROR'); fputs($fp,$header); $output = ""; $flag = false; $b = ""; $chunked=false; while (!feof($fp)) { $b = fgets($fp,4096); if(preg_match('/Transfer-Encoding: chunked\r/',$b)){ $chunked = true; } if($flag) $output .= $b; if(strlen(trim($b))==0) $flag = true; } fclose($fp); if($chunked) $output = $this->unchunk($output); echo $output;

Ca fonctionne chez moi sans soucis.

comments powered by Disqus