Implémentation de l'encodage en bloc dans .NET (ou au moins pseudo-code)
-
11-07-2019 - |
Question
J'ai écrit un client TCP brut pour les requêtes HTTP / HTTPS, mais j'ai des problèmes avec les réponses d'encodage en bloc. HTTP / 1.1 est une exigence donc je devrais le supporter.
Le TCP brut est une exigence commerciale que je dois respecter. Par conséquent, je ne peux pas passer à .NET HTTPWebRequest / HTTPWebResponse Cependant, s’il existe un moyen de convertir une demande / réponse HTTP RAW en HTTPWebRequest / HTTPWebResponse qui fonctionnerait.
La solution
Le meilleur point de départ est la spécification http 1.1 , qui contient comment fonctionne la fragmentation. Plus précisément la section 3.6.1.
3.6.1 Codage de transfert en bloc
Le codage en bloc modifie la corps d'un message afin de
transférer comme une série de morceaux, chacun avec son propre indicateur de taille,
suivi d'un trailer FACULTATIF contenant des champs d'en-tête d'entité. Ce permet au contenu produit dynamiquement de être transféré avec le
informations nécessaires à la destinataire pour vérifier qu'il a
reçu le message complet.Chunked-Body = *chunk last-chunk trailer CRLF chunk = chunk-size [ chunk-extension ] CRLF chunk-data CRLF chunk-size = 1*HEX last-chunk = 1*("0") [ chunk-extension ] CRLF chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) chunk-ext-name = token chunk-ext-val = token | quoted-string chunk-data = chunk-size(OCTET) trailer = *(entity-header CRLF)
Le champ de taille de morceau est une chaîne de chiffres hexadécimaux indiquant la taille de
le morceau. Le codage en bloc est terminé par un morceau dont la taille est
zéro, suivi de la bande-annonce, qui se termine par une ligne vide.La bande-annonce permet à l'expéditeur de inclure un en-tête HTTP supplémentaire
champs à la fin du message. le Le champ d'en-tête de la bande-annonce peut être utilisé pour indiquer quels champs d'en-tête sont inclus dans une remorque (voir section 14.40).
En supposant que vous ayez déjà lu l'en-tête de la réponse et que vous pointez sur l'octet suivant du flux, votre pseudo-code se présente comme suit:
done = false;
uint8 bytes[];
while (!done)
{
chunksizeString = readuntilCRLF(); // read in the chunksize as a string
chunksizeString.strip(); // strip off the CRLF
chunksize = chunksizeString.convertHexString2Int(); // convert the hex string to an integer.
bytes.append(readXBytes(chunksize)); // read in the x bytes and append them to your buffer.
readCRLF(); // read the trailing CRLF and throw it away.
if (chunksize == 0)
done = true; //
}
// now read the trailer if any
// trailer is optional, so it may be just the empty string
trailer = readuntilCRLF()
trailer = trailer.strip()
if (trailer != "")
readCRLF(); // read out the last CRLF and we are done.
Il s’agit d’ignorer la partie d’extension de bloc, mais comme elle est délimitée par un " ;; il devrait être facile de le séparer. Cela devrait être suffisant pour vous aider à démarrer. N'oubliez pas que la chaîne de taille de bloc n'a pas de début "0x".
Autres conseils
Pour la référence future aussi, j'ai trouvé ceci:
length := 0
read chunk-size, chunk-extension (if any) and CRLF
while (chunk-size > 0) {
read chunk-data and CRLF
append chunk-data to entity-body
length := length + chunk-size
read chunk-size and CRLF
}
read entity-header
while (entity-header not empty) {
append entity-header to existing header fields
read entity-header
}
Content-Length := length
Remove "chunked" from Transfer-Encoding