es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Usando la solicitud de rango HTTP para obtener solo el contenido en la parte de Contenido, Python.

Tengo el siguiente código en Python en el que quiero obtener algunas partes del archivo en el servidor mediante una solicitud HTTP Range. Estoy definiendo el punto final inferior y el punto final superior. Lo que quiero lograr es obtener bytes desde el punto final inferior hasta el punto final superior solo en la parte de contenido de la respuesta parcial de contenido HTTP.

El contenido original del archivo es el siguiente:

www.cs.bilkent.edu.tr/file.txt
www.cs.bilkent.edu.tr/folder2/temp.txt
www.textfiles.com/100/balls.txt
www.cs.bilkent.edu.tr/~cs421/fall21/project1/bilkent.txt
www.textfiles.com/games/arcana.txt
www.cs.bilkent.edu.tr/~cs421/cs421/abc.txt
www.cs.bilkent.edu.tr/~cs421/fall21/project1/files/numbers.txt
www.cs.bilkent.edu.tr/~cs421/fall21/project1/files/decrypted_file_1.txt
www.textfiles.com/100/captmidn.txt

Por ejemplo, cuando establezco el punto final inferior en 0 y el punto final superior en 200, quiero obtener los bytes que comienzan con “www.cs.bilkent.edu.tr/file.txt” hasta 200 bytes.

Sin embargo, cuando ejecuto el código con esos valores, obtengo lo siguiente:

HTTP/1.1 206 Partial Content
Date: Sun, 19 Dec 2021 07:04:52 GMT
Server: Apache/2.4.25 (FreeBSD) OpenSSL/1.0.2u-freebsd PHP/7.4.15
Last-Modified: Sat, 06 Nov 2021 11:11:25 GMT
ETag: “197-5d01cd2175dc5”
Accept-Ranges: bytes
Content-Length: 201
Conten

Creo que los bytes están comenzando desde el principio del encabezado de la respuesta.

El código es el siguiente:

import socket

server_port = 80
clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
hostname = "www.cs.bilkent.edu.tr"
clientSocket.connect((hostname, server_port))  # Esta línea inicia la conexión
filename = "/~cs421/fall21/project1/index1.txt"
lower_endpoint = 0
upper_endpoint = 200
request = ("GET %s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%s-%s\r\n\r\n" % (
                    filename, hostname, lower_endpoint, upper_endpoint
                )).encode()

power = 1
while power < upper_endpoint - lower_endpoint:
    power *= 2

clientSocket.send(request)
rcvpkt = clientSocket.recv(power)
rcv_str = rcvpkt.decode()

print(rcv_str)

Por favor, no recomiende el uso de bibliotecas de cliente HTTP de terceros.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para lograr el resultado deseado de obtener bytes desde lower_endpoint hasta upper_endpoint en la parte de contenido de la respuesta parcial de contenido HTTP, debes modificar tu código para manejar correctamente los datos recibidos del servidor.

    La respuesta parcial de contenido HTTP indica que solo se ha devuelto una parte del contenido, que es lo que querías, pero como señalaste, los datos recibidos comienzan con la información del encabezado HTTP en lugar del contenido real.

    Para obtener el contenido a partir del desplazamiento de byte deseado, debes analizar los encabezados de respuesta HTTP para determinar el intervalo de bytes que realmente devolvió el servidor. El servidor puede devolver menos bytes de los solicitados o puede comenzar en un desplazamiento diferente.

    Puedes usar el campo de encabezado Content-Range para determinar el intervalo de bytes devuelto realmente. El formato de este encabezado es “bytes x-y/total”, donde x e y denotan el intervalo de bytes devuelto y total es el tamaño total del contenido.

    Puedes analizar este campo de encabezado de la respuesta utilizando expresiones regulares u otras funciones de manipulación de cadenas. Una vez que tengas el intervalo de bytes devuelto realmente, puedes extraer los bytes de contenido a partir del lower_endpoint deseado.

    Aquí tienes una versión actualizada de tu código que incorpora estas modificaciones:

    import socket
    import re
    
    server_port = 80
    clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    host_name = "www.cs.bilkent.edu.tr"
    clientSocket.connect((host_name, server_port))  # Esta línea inicia la conexión
    file_name = "/~cs421/fall21/project1/index1.txt"
    lower_endpoint = 0
    upper_endpoint = 200
    request = ("GET %s HTTP/1.1\r\nHost: %s\r\nRange: bytes=%s-%s\r\n\r\n" % (
                    file_name, host_name, lower_endpoint, upper_endpoint
                )).encode()
    
    power = 1
    while power < upper_endpoint - lower_endpoint:
        power *= 2
    
    clientSocket.send(request)
    rcvpkt = clientSocket.recv(power)
    rcv_str = rcvpkt.decode()
    
    # Analiza el encabezado Content-Range para obtener el intervalo de bytes devuelto realmente
    match = re.search(r'(\d+)-(\d+)/(\d+)', rcv_str)
    if match:
        start = int(match.group(1))
        end = int(match.group(2))
        total = int(match.group(3))
    
        # Extrae los bytes de contenido a partir del lower_endpoint deseado
        content = rcv_str[rcv_str.index('\r\n\r\n')+4:]
        actual_start = start + len(content) - (end - start) + 1
        actual_end = end + len(content) - (end - start) + 1
        content = content[max(0, lower_endpoint-actual_start):min(upper_endpoint-actual_start, actual_end-start)]
    
        print(content)
    else:
        print("Encabezado Content-Range no encontrado")
    

    Este código analiza el encabezado Content-Range utilizando una expresión regular para obtener el intervalo de bytes que realmente devolvió el servidor. Luego, extrae los bytes de contenido de la respuesta a partir del desplazamiento adecuado según el intervalo de bytes real devuelto. Finalmente, imprime los bytes de contenido que se encuentran dentro del intervalo especificado por lower_endpoint y upper_endpoint.

    Ten en cuenta que este código asume que toda la respuesta cabe en el paquete recibido. En la práctica, puede ser necesario recibir varios paquetes para obtener la respuesta completa. Además, este código asume que el encabezado Content-Range siempre está presente en la respuesta, lo que puede no ser el caso en todos los servidores. Debes agregar un código de manejo de errores y validación apropiado para manejar estos casos.

Comments are closed.