servidor peticiones peticion para metodo enviar conectar codigo cliente ruby http

ruby - peticiones - ¿Cómo leo solo x cantidad de bytes del cuerpo usando Net:: HTTP?



peticiones get arduino (6)

Parece que los métodos de Ruby''s Net :: HTTP son todo o nada cuando se trata de leer el cuerpo de una página web. ¿Cómo puedo leer, decir, solo los primeros 100 bytes del cuerpo?

Intento leer desde un servidor de contenido que devuelve un breve mensaje de error en el cuerpo de la respuesta si el archivo solicitado no está disponible. Necesito leer lo suficiente del cuerpo para determinar si el archivo está allí. Los archivos son enormes, por lo que no quiero obtener todo el cuerpo solo para comprobar si el archivo está disponible.


No puedes. Pero, ¿por qué lo necesitas? Seguramente, si la página solo dice que el archivo no está disponible, entonces no será una gran página (es decir, por definición, el archivo no estará allí)?


Para leer el cuerpo de una solicitud HTTP en fragmentos, deberá usar Net::HTTPResponse#read_body así:

http.request_get(''/large_resource'') do |response| response.read_body do |segment| print segment end end


Este es un hilo viejo, pero la cuestión de cómo leer solo una parte de un archivo a través de HTTP en Ruby sigue sin ser respondida, según mi investigación. Aquí hay una solución que se me ocurrió al parchear mono Net :: HTTP un poco:

require ''net/http'' # provide access to the actual socket class Net::HTTPResponse attr_reader :socket end uri = URI("http://www.example.com/path/to/file") begin Net::HTTP.start(uri.host, uri.port) do |http| request = Net::HTTP::Get.new(uri.request_uri) # calling request with a block prevents body from being read http.request(request) do |response| # do whatever limited reading you want to do with the socket x = response.socket.read(100); # be sure to call finish before exiting the block http.finish end end rescue IOError # ignore end

El rescate captura el IOError que se lanza cuando se llama a HTTP.finish prematuramente.

FYI, el socket dentro del objeto HTTPResponse no es un verdadero objeto IO (es una clase interna llamada BufferedIO ), pero es muy fácil aplicar un parche simulado que también imita los métodos IO que necesita. Por ejemplo, otra biblioteca que estaba usando (exifr) necesitaba el método readchar , que era fácil de agregar:

class Net::BufferedIO def readchar read(1)[0].ord end end


¿No debería simplemente usar una solicitud HTTP HEAD (método Ruby Net::HTTP::Head ) para ver si el recurso está allí, y solo proceder si obtiene una respuesta 2xx o 3xx? Esto supone que su servidor está configurado para devolver un código de error 4xx si el documento no está disponible. Yo diría que esta fue la solución correcta.

Una alternativa es solicitar el encabezado HTTP y observar el valor del encabezado de content-length del content-length en el resultado: si su servidor está configurado correctamente, debe poder distinguir fácilmente la diferencia de longitud entre un mensaje corto y un documento largo. Otra alternativa: establecer el campo de encabezado de content-range en la solicitud (que de nuevo supone que el servidor se comporta correctamente WRT la especificación HTTP).

No creo que resolver el problema en el cliente después de haber enviado la solicitud GET sea el camino a seguir: en ese momento, la red ha realizado un gran trabajo y no ahorrará recursos desperdiciados.

Referencia: definiciones de encabezado http


¿Estás seguro de que el servidor de contenido solo devuelve una página breve de error?

¿No establece también HTTPResponse en algo apropiado como 404. En cuyo caso puede atrapar la excepción derivada de HTTPClientError (probablemente HTTPNotFound ) que se HTTPNotFound al acceder a Net::HTTP.value() .

Si obtiene un error, su archivo no estaba allí, si obtiene 200, el archivo está comenzando a descargar y puede cerrar la conexión.


Quería hacer esto una vez, y lo único que podía pensar era en Net::HTTP#read_body_0 métodos Net::HTTP#read_body y Net::HTTP#read_body_0 para aceptar un parámetro de longitud, y luego en el anterior simplemente pasar el parámetro de longitud al método read_body_0 , donde puedes leer solo tanto como bytes de longitud.