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.
Pas de commentaire pour le moment
Trackbacks
Pour ajouter un trackback (retrolien) sur ce ticket, utilisez cette adresse: http://www.metal3d.org/index.php/trackback/default/tb?id=blog%2F107