Передача данных из HTTP GET в HTTP POST / PUT - PullRequest
2 голосов
/ 30 марта 2012

Я бы хотел передавать данные из HTTP-запроса GET в HTTP-запрос POST или PUT. Я бы предпочел использовать Ruby и уже пытался использовать EventMachine и EM-HTTP-запрос .

Вот моя попытка вызвать с помощью:

HttpToS3Stream.new(src_url, dest_bucket, dest_key, aws_access_key_id, aws_secret_access_key)

http_to_s3_stream.rb

require 'em-http-request'

class HttpToS3Stream

  def initialize(http_url, s3_bucket, s3_key, s3_access_key_id, s3_secret_access_key)
    @http_url = http_url
    @s3_bucket = s3_bucket
    @s3_key = s3_key
    @s3_access_key_id = s3_access_key_id
    @s3_secret_access_key = s3_secret_access_key
    go
  end

  private

  def go
    EM.run {
      # initialize get stream, without listener does not start request
      @get_stream = HttpGetStream.new(@http_url)

      # initialize put stream, send content length, request starts
      @put_stream = S3PutStream.new(@s3_bucket, @s3_key, @s3_access_key_id, @s3_secret_access_key, @get_stream.content_length)

      # set listener on get stream, starts request, pipes data to put stream
      @get_stream.listener = @put_stream
    }
  end

end

http_get_stream.rb

require 'httparty'
require 'em-http-request'

class HttpGetStream

  def initialize(http_url, listener = nil)
    @http_url = http_url
    self.listener = listener
  end

  def listener=(listener)
    @listener = listener
    listen unless @listener.nil?
  end

  def content_length
    response = HTTParty.head(@http_url)
    response['Content-length']
  end

  private

  def listen
    http = EventMachine::HttpRequest.new(@http_url).get
    http.stream do |chunk|
      @listener.send_data chunk
    end
    http.callback do |chunk|
      EventMachine.stop
    end
  end

end

s3_put_stream.rb

require 'em-http-request'

class S3PutStream

  def initialize(s3_bucket, s3_key, s3_access_key_id, s3_secret_access_key, content_length = nil)
    @s3_bucket = s3_bucket
    @s3_key = s3_key
    @s3_access_key_id = s3_access_key_id
    @s3_secret_access_key = s3_secret_access_key
    @content_length = content_length
    @bytes_sent = 0
    listen
  end

  def send_data(data)
    @bytes_sent += data.length
    @http.on_body_data data
  end

  private

  def listen
    raise 'ContentLengthRequired' if @content_length.nil?
    @http = EventMachine::HttpRequest.new(put_url).put(
      :head => {
        'Content-Length' => @content_length,
        'Date' => Time.now.getutc,
        'Authorization' => auth_key
      }
    )
    @http.errback { |error| puts "error: #{error}" }
  end

  def put_url
    "http://#{@s3_bucket}.s3.amazonaws.com/#{@s3_key}"
  end

  def auth_key
    "#{@s3_access_key_id}:#{@s3_secret_access_key}"
  end

end

HttpToS3Stream.new(src_url, dest_bucket, dest_key, aws_access_key_id, aws_secret_access_key)

Вроде бы работает, но всегда останавливается на 33468 байт. Не уверен, о чем идет речь. Теперь, передавая куски непосредственно в @listener.send_data, он обрабатывает все тело GET. Однако загрузка не происходит успешно.

Как мне заставить это работать? И есть ли название для того, что я пытаюсь сделать? У меня проблемы с поиском дополнительной информации.

Любая помощь приветствуется.

...