2012-09-11 39 views
5

Quiero proxy de archivos remotos a través de una aplicación Sinatra. Esto requiere transmitir una respuesta HTTP con encabezados desde una fuente remota al cliente, pero no puedo encontrar la manera de configurar los encabezados de la respuesta mientras uso la API de transmisión dentro del bloque proporcionado por Net::HTTP#get_response.Respuesta de transmisión de Sinatra con encabezados

Por ejemplo, este no establece las cabeceras de respuesta:

get '/file' do 
    stream do |out| 
    uri = URI("http://manuals.info.apple.com/en/ipad_user_guide.pdf") 
    Net::HTTP.get_response(uri) do |file| 
     headers 'Content-Type' => file.header['Content-Type'] 

     file.read_body { |chunk| out << chunk } 
    end 
    end 
end 

Y esto da como resultado el error: Net::HTTPOK#read_body called twice (IOError):

get '/file' do 
    response = nil 
    uri = URI("http://manuals.info.apple.com/en/ipad_user_guide.pdf") 
    Net::HTTP.get_response(uri) do |file| 
    headers 'Content-Type' => file.header['Content-Type'] 

    response = stream do |out| 
     file.read_body { |chunk| out << chunk } 
    end 
    end 
    response 
end 

Respuesta

3

puedo estar equivocado, pero después de pensar un poco acerca de esto parece Para mí, al configurar los encabezados de respuesta desde el interior del bloque de ayuda stream, esos encabezados no se aplican a la respuesta porque la ejecución de ese bloque en realidad es diferida. Entonces, probablemente, el bloque se evalúa y los encabezados de respuesta se configuran antes de comienza a ejecutarse.

Una posible solución para esto es emitir una solicitud HEAD antes de volver a reproducir el contenido del archivo.

Por ejemplo:

get '/file' do 
    uri = URI('http://manuals.info.apple.com/en/ipad_user_guide.pdf') 

    # get only header data 
    head = Net::HTTP.start(uri.host, uri.port) do |http| 
    http.head(uri.request_uri) 
    end 

    # set headers accordingly (all that apply) 
    headers 'Content-Type' => head['Content-Type'] 

    # stream back the contents 
    stream do |out| 
    Net::HTTP.get_response(uri) do |f| 
     f.read_body { |ch| out << ch } 
    end 
    end 
end 

Puede que no sea ideal para su caso de uso debido a la solicitud adicional, pero debe ser lo suficientemente pequeño como para no ser un gran problema (retraso) y se añade el beneficio que su aplicación puede reaccionar si esa solicitud falla antes de devolver cualquier información.

Espero que ayude.

Cuestiones relacionadas