2012-09-11 5 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 

을 그리고이 오류가 발생합니다 :

예를 들어,이 응답 헤더를 설정하지 않습니다 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 

답변

3

내가 틀릴 수도 있지만, 이것에 대해 조금 생각 후 나타납니다 나에게 응답 헤더를 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 

이 때문에 추가 요청의 사용 사례에 적합하지 않을 수 있지만 문제 (지연)을 많이하지에 충분히 작은되어야하며, 그것은 혜택을 추가하는 요청이 실패하면 데이터를 다시 보내기 전에 앱에서 반응 할 수 있습니다.

희망이 있습니다.

관련 문제