class Rodent::Goliath::Middleware

Public Class Methods

new(app, header_proxy_name = 'Rodent-Proxy') click to toggle source
Calls superclass method
# File lib/rodent/goliath/middleware.rb, line 12
def initialize(app, header_proxy_name = 'Rodent-Proxy')
  @header_proxy_name = header_proxy_name
  super(app)
end

Public Instance Methods

hook_into_callback_chain(env, *args) click to toggle source
# File lib/rodent/goliath/middleware.rb, line 17
def hook_into_callback_chain(env, *args)
  async_callback = env['async.callback']

  downstream_callback = proc do |status, headers, response|
    result_response = [status, headers, response]
    if proxy_type = headers.delete(@header_proxy_name)
      body = response.respond_to?(:body) ? response.body.join : response
      result_response = safely(env) { proxy_request(env, proxy_type, body, headers) }
    end
    async_callback.call(result_response) unless result_response == ::Goliath::Connection::AsyncResponse
  end

  env['async.callback'] = downstream_callback
end

Protected Instance Methods

bind_consumer(consumer, async_callback, headers) click to toggle source
# File lib/rodent/goliath/middleware.rb, line 50
def bind_consumer(consumer, async_callback, headers)
  consumer.consume do
    consumer.on_delivery do |metadata, payload|
      response = MultiJson.load(payload)
      response['headers']['Content-Length'] = response['body'].to_s.bytes.count.to_s
      response['headers']['Content-Type'] = 'application/json'
      async_callback.call([response['status'], headers.merge(response['headers']), response['body']])
      metadata.ack
      consumer.cancel
    end
  end
end
proxy_request(env, type, body, headers = {}) click to toggle source
# File lib/rodent/goliath/middleware.rb, line 33
def proxy_request(env, type, body, headers = {})
  async_callback = env['async.callback']

  message_id = BSON::ObjectId.new.to_s

  env.channels.execute(false) do |channel|
    replies_queue = channel.queue(message_id, exclusive: true, auto_delete: true)

    consumer = AMQP::Consumer.new(channel, replies_queue)
    bind_consumer(consumer, async_callback, headers)

    channel.direct('rodent.requests').publish(body, routing_key: type, message_id: message_id, reply_to: replies_queue.name)
  end

  ::Goliath::Connection::AsyncResponse
end