2012-09-11 12 views
5

Sinatraアプリケーションを使用してリモートファイルをプロキシする必要があります。これには、リモートソースからのヘッダーをHTTPレスポンスでクライアントにストリーミングする必要がありますが、Net::HTTP#get_responseで提供されるブロック内でストリーミングAPIを使用しているときに、応答のヘッダーを設定する方法がわかりません。Sinatraのヘッダー付きストリーミング応答

たとえば、これはレスポンスヘッダを設定しません。

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 

そして、これはエラーになり:私は間違っている可能性

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 

答えて

3

が、これについて少し考えた後、それが表示されます。Net::HTTPOK#read_body called twice (IOError)応答ヘッダーをstreamヘルパーブロックの内側から設定すると、そのブロックの実行が実際にはであり、応答がであるため、応答には適用されません。したがって、ブロックが評価され、応答ヘッダーがに設定されてから、の実行が開始されます。

この問題を回避するには、ファイルの内容をストリーミングする前にHEADリクエストを発行することが考えられます。例えば

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 

それが原因で追加のリクエストをご利用の場合に理想的ではないかもしれないが、問題(遅延)の多くも、それはその恩恵を追加しないために十分に小さくなければなりませんそのリクエストが失敗した場合にデータを返送する前に、アプリが反応する可能性があります。

希望します。

関連する問題