impress/lib/rocketamf/remote_gateway/request.rb

96 lines
2.6 KiB
Ruby

module RocketAMF
class RemoteGateway
class Request
ERROR_CODE = 'AMFPHP_RUNTIME_ERROR'
def initialize(service, method, *params)
@service = service
@method = method
@params = params
end
def fetch
uri = @service.gateway.uri
data = envelope.serialize
# TODO: re-enable if we go back to using threads
if false && defined?(EventMachine) && EventMachine.respond_to?(:reactor_running?) && EventMachine.reactor_running?
req = EM::HttpRequest.new(uri).post :body => data
response_body = req.response
else
req = Net::HTTP::Post.new(uri.path)
req.body = data
begin
res = Net::HTTP.new(uri.host, uri.port).start { |http| http.request(req) }
rescue Exception => e
raise ConnectionError, e.message
end
case res
when Net::HTTPSuccess
response_body = res.body
else
error = nil
begin
res.error!
rescue Exception => scoped_error
error = scoped_error
end
raise ConnectionError, error.message
end
end
begin
result = RocketAMF::Envelope.new.populate_from_stream(response_body)
rescue Exception => e
raise ConnectionError, e.message
end
first_message_data = result.messages[0].data
if first_message_data.respond_to?(:[]) && first_message_data[:code] == ERROR_CODE
raise AMFError.new(first_message_data)
end
result
end
private
def envelope
output = Envelope.new
output.messages << wrapper_message
output
end
def wrapper_message
message = Message.new 'null', '/1', [remoting_message]
end
def remoting_message
message = Values::RemotingMessage.new
message.source = @service.name
message.operation = @method
message.body = @params
message
end
end
class ConnectionError < RuntimeError
def initialize(message)
@message = message
end
def message
"Error connecting to gateway: #{@message}"
end
end
class AMFError < RuntimeError
DATA_KEYS = [:details, :line, :code]
attr_reader *DATA_KEYS
attr_reader :message
def initialize(data)
DATA_KEYS.each do |key|
instance_variable_set "@#{key}", data[key]
end
@message = data[:description]
end
end
end
end