lib/invoker/power/balancer.rb in invoker-1.2.0.pre1 vs lib/invoker/power/balancer.rb in invoker-1.2.0.pre2

- old
+ new

@@ -1,7 +1,8 @@ require 'em-proxy' require 'http-parser' +require "invoker/power/http_parser" module Invoker module Power class InvokerHttpProxy < EventMachine::ProxyServer::Connection attr_accessor :host, :ip, :port @@ -17,41 +18,10 @@ super start_tls end end - class BalancerParser - attr_accessor :host, :parser - def initialize - @parser = HTTP::Parser.new() - @header = {} - @parser.on_headers_complete { headers_received() } - @parser.on_header_field { |field_name| - @last_key = field_name - } - @parser.on_header_value { |value| header_value_received(value) } - end - - def headers_received - @header_completion_callback.call(@header) - end - - def header_value_received(value) - @header[@last_key] = value - end - - def on_headers_complete(&block) - @header_completion_callback = block - end - - def reset; @parser.reset(); end - - def <<(data) - @parser << data - end - end - class Balancer attr_accessor :connection, :http_parser, :session, :protocol DEV_MATCH_REGEX = /([\w-]+)\.dev(\:\d+)?$/ def self.run(options = {}) @@ -69,53 +39,46 @@ end def initialize(connection, protocol) @connection = connection @protocol = protocol - @http_parser = BalancerParser.new() + @http_parser = HttpParser.new(protocol) @session = nil @buffer = [] end - # insert X_FORWARDED_PROTO_ so as rails can identify the request as coming from - # https - def insert_forwarded_proto_header(data) - if data =~ /\r\n\r\n/ && data !~ /X_FORWARDED_PROTO/i && protocol == 'https' - data.gsub(/\r\n\r\n/, "\r\nX_FORWARDED_PROTO: #{protocol}\r\n\r\n") - else - data - end - end - def install_callbacks - http_parser.on_headers_complete { |header| headers_received(header) } + http_parser.on_headers_complete { |headers| headers_received(headers) } + http_parser.on_message_complete { |full_message| complete_message_received(full_message) } connection.on_data { |data| upstream_data(data) } connection.on_response { |backend, data| backend_data(backend, data) } connection.on_finish { |backend, name| frontend_disconnect(backend, name) } end - def headers_received(header) + def complete_message_received(full_message) + connection.relay_to_servers(full_message) + http_parser.reset + end + + def headers_received(headers) + if @session + return + end @session = UUID.generate() - dns_check_response = select_backend_config(header['Host']) + dns_check_response = select_backend_config(headers['Host']) if dns_check_response && dns_check_response.port connection.server(session, host: '0.0.0.0', port: dns_check_response.port) - connection.relay_to_servers(insert_forwarded_proto_header(@buffer.join)) - @buffer = [] else return_error_page(404) + http_parser.reset connection.close_connection_after_writing end end def upstream_data(data) - unless session - @buffer << data - append_for_http_parsing(data) - nil - else - insert_forwarded_proto_header(data) - end + append_for_http_parsing(data) + nil end def append_for_http_parsing(data) http_parser << data rescue HTTP::Parser::Error @@ -129,10 +92,9 @@ end def frontend_disconnect(backend, name) http_parser.reset unless @backend_data - Invoker::Logger.puts("\nApplication #{name} not running. Returning error page.".color(:red)) return_error_page(503) end @backend_data = false connection.close_connection_after_writing if backend == session end