php insère le nombre de caractères HEX avant le contenu

Je déplace un site Web sur un nouveau serveur. (L’ancien serveur avait php 5.3.2, le nouveau a php 5.5.9) Centos, httpd Apache / 2.2.26.

J’ai copié des fichiers et cela fonctionne bien sauf la seule chose étrange: un numéro HEX étrange est inséré avant le contenu des pages:

entrer la description de l'image ici

De plus, en bas de la page, 0 est inséré après la .

J’ai remarqué deux choses:

1) Dans mon cas, seuls deux en-têtes sont envoyés à partir du script php:

 header("HTTP/1.1 200 OK"); header("Status: 200"); 

Si je commente le premier en-tête, ça ira, pas de chiffres étranges.

2) On dirait que ce nombre est le nombre de caractères sur la page (je l’ai vérifié). Et si la page est inférieure à 8000 caractères, le nombre n’apparaît pas, mais si la page contient 8001 caractères, 1F41 apparaît

PS J’ai été conseillé de supprimer toutes les nomenclatures des fichiers. Les fichiers étaient corrects – déjà sans nomenclature. Donc, il ne s’agit pas de BOM.

UPD: J’ai fait un test très simple (index.php):

  Lorem Ipsum ... 8000 characters 

Tout va bien.

  Lorem Ipsum ... 8001 characters 

Le bug arrive 1f41 avant Lorem Ipsum.

Ce n’est pas PHP ni une nomenclature. Vous avez un problème avec Content-Transfer-Encoding.

Le serveur envoie un codage en Chunked (généralement lorsque la Content-Length du Content-Length n’est pas disponible), ce que le client ne sait apparemment pas comment gérer, ou la combinaison d’en-têtes lui fait croire qu’il peut contourner le détournement.

Par conséquent, ce qui est en fait la “longueur du segment suivant” est interprété par le client, et vous le voyez comme un bit hexadécimal avant le contenu:

 05 These 05 Are 03 the 1F first characters of the senten 03 ce. 

au lieu de

 Content-Length: 48 These are the first characters of the sentence. 

( J’ai calculé les longueurs à l’oeil, elles sont probablement fausses )

La cause probable est que vous disposez d’une sorte de mise en mémoire tampon qui interfère avec le codage de contenu. Si tout rest dans le tampon, tout va bien, un Content-Length est disponible, envoyé et Bob est votre oncle. Mais si vous envoyez plus que les 8 000 octets du tampon, le tampon est vidé et il se passe quelque chose d’inhabituel. Essayez de regarder dans la documentation pour zlib et la mémoire tampon de sortie, vous pourriez avoir des conflits dans php.ini entre ce que fait Apache et ce que fait PHP.

Liens intéressants montrant à quel point 8000 est (était?) Une taille de mémoire tampon utilisée dans certaines parties d’Apache:

https://bugs.php.net/bug.php?id=45945

https://serverfault.com/questions/366996/how-can-the-apache-2-2-deflate-module-length-limit-be-increased

Ce dernier lien me propose de vous suggérer d’essayer de vérifier si zlib, mod_gzip, ob_gzhandler et / ou mod_deflate sont activés, voire en conflit, ou d’essayer d’échanger l’un pour l’autre.

Mise à jour (selon le commentaire)

L’ajout de l’en-tête Transfer-Encoding approprié résout le problème.

Alors qu’est-ce qui s’est vraiment passé? Nous soaps que la sortie a été correctement codée en blocs (c’est-à-dire que le fragment lui-même était correct), et le client a été capable de l’interpréter après avoir été averti. Donc, ce qui manquait était simplement la connaissance du contenu en morceaux , ce qui semble absurde et un peu bogué: pour tout ce que le contenu devait contenir, il devait savoir qu’il serait fragmenté (d’oh!), Donc il lui incombait d’append le contenu approprié. en-tête, et pourtant il ne l’a pas fait (ou l’a fait, mais quelque chose l’a dénudé ), jusqu’à ce que l’OP corrige la situation en ajoutant lui-même un en-tête à la main.

Le problème est maintenant résolu, mais je pense qu’il doit y avoir encore un bogue quelque part dans le stream de travail, que ce soit dans les modules, dans l’application ou dans le traitement des en-têtes.

Comme discuté dans la salle de discussion PHP hier, 9F 1A est la nomenclature pour l’ encodage UTF-16BE

Dans mon cas, seuls deux en-têtes sont envoyés à partir du script php:

en-tête (“HTTP / 1.1 200 OK”); en-tête (“Statut: 200”);

Qu’est-ce qui se passe ici? Pourquoi mettez-vous les deux? L’une est une réponse http correcte, l’autre est une réponse CGI. Vous ne devriez pas avoir à définir non plus, car PHP sera par défaut à 200 OK si le script se termine. Et définir un en-tête de style CGI est probablement faux, à moins que vous ne lanciez définitivement PHP en mode CGI via Apache.