Implementación de codificación fragmentada en .NET (o al menos pseudocódigo)
-
11-07-2019 - |
Pregunta
Escribí un cliente TCP sin procesar para solicitudes HTTP / HTTPS, sin embargo, tengo problemas con las respuestas de codificación fragmentadas. HTTP / 1.1 es un requisito, por lo tanto, debería admitirlo.
Raw TCP es un requisito comercial que debo mantener, por lo tanto, no puedo cambiar a .NET HTTPWebRequest / HTTPWebResponse Sin embargo, si hay una manera de convertir una solicitud / respuesta HTTP RAW en HTTPWebRequest / HTTPWebResponse que funcionaría.
Solución
El mejor lugar para comenzar es la especificación http 1.1 , que establece a ver cómo funciona el fragmentado. Específicamente la sección 3.6.1.
3.6.1 Codificación de transferencia fragmentada
La codificación fragmentada modifica el cuerpo de un mensaje para
transfiérelo como una serie de trozos, cada uno con su propio indicador de tamaño,
seguido de un trailer OPCIONAL que contiene campos de encabezado de entidad. Esta permite contenido producido dinámicamente para ser transferido junto con el
información necesaria para el destinatario para verificar que tiene
recibió el mensaje completo.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)
El campo de tamaño de fragmento es una cadena de dígitos hexadecimales que indican el tamaño de
el trozo La codificación fragmentada es terminado por cualquier fragmento cuyo tamaño es
cero, seguido por el trailer, que termina con una línea vacía.El avance le permite al remitente incluir encabezado HTTP adicional
campos al final del mensaje. los El campo de encabezado de tráiler se puede usar para indicar qué campos de encabezado son incluido en un trailer (ver sección 14.40).
Suponiendo que ya ha leído el encabezado de la respuesta y está apuntando al siguiente byte en la secuencia, su pseudocódigo se vería así:
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.
Esto ignora la porción de extensión de fragmento, pero dado que está delimitada con un " ;; " debería ser fácil dividirlo. Esto debería ser suficiente para comenzar. Tenga en cuenta que la cadena de tamaño de fragmento no tiene un " 0x " ;.
Otros consejos
Para la referencia futura también encontré esto:
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