Class: RFlow::Components::HTTP::Server

Inherits:
RFlow::Component
  • Object
show all
Defined in:
lib/rflow/components/http/server.rb

Overview

Implements a HTTP server based on eventmachine_httpserver. Accepts incoming HTTP connections, marshals the HTTP request into an RFlow message, annotates the message with a bit of provenance (see below) and then sends the message out its #request_port. When a HTTP response message is received on #response_port, checks the provenance to see if it matches an underlying TCP/HTTP connection and, if so, creates an actual HTTP response from the incoming message and sends it to the client.

The HTTP request message sent from the HTTP server component utilizes the RFlow::Message provenance feature to annotate a request message with a bit of metadata that allows subsequent response messages to be matched to their underlying TCP/HTTP connections. This means that any component that processes HTTP request messages to generate response messages must copy the provenance from the request message to the response message.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#request_portRFlow::Component::OutputPort (readonly)

Produces RFlow::Messages of type Message::Data::HTTP::Request representing requests that have arrived on the socket managed by the component. Each features provenance that must be copied to any response message.

Returns:

  • (RFlow::Component::OutputPort)


35
# File 'lib/rflow/components/http/server.rb', line 35

output_port :request_port

#response_portRFlow::Component::InputPort (readonly)

Expects RFlow::Messages of type Message::Data::HTTP::Response representing responses being sent back corresponding to previously received requests. Each response should have provenance copied from the request it’s responding to.

Returns:

  • (RFlow::Component::InputPort)


28
# File 'lib/rflow/components/http/server.rb', line 28

input_port :response_port

Instance Method Details

#configure!(config) ⇒ void

This method returns an undefined value.

RFlow-called method at startup.



44
45
46
47
48
49
50
51
52
53
# File 'lib/rflow/components/http/server.rb', line 44

def configure!(config)
  @listen = config['listen'] ? config['listen'] : '127.0.0.1'
  @port = config['port'] ? config['port'].to_i : 8000
  @proxy_real_client_ip_header = config.has_key?('proxy-real-client-ip-header') ? config['proxy-real-client-ip-header'] : 'X-Real-IP'
  @proxy_real_client_port_header = config.has_key?('proxy-real-client-port-header') ? config['proxy-real-client-port-header'] : 'X-Real-Port'
  @proxy_real_server_ip_header = config.has_key?('proxy-real-server-ip-header') ? config['proxy-real-server-ip-header'] : 'X-Server-IP'
  @proxy_real_server_port_header = config.has_key?('proxy-real-server-port-header') ? config['proxy-real-server-port-header'] : 'X-Server-Port'
  @connections = {}
  @closed_connections = ActiveSupport::Cache::MemoryStore.new(expires_in: 5.minutes)
end

#process_message(input_port, input_port_key, connection, message) ⇒ void

This method returns an undefined value.

RFlow-called method upon message arrival.

Filters for messages that pertain to this component and have active connections by inspecting the provenance, specifically the context attribute that we stored originally.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/rflow/components/http/server.rb', line 72

def process_message(input_port, input_port_key, connection, message)
  return unless message.data_type_name == 'RFlow::Message::Data::HTTP::Response'
  my_events = message.provenance.find_all {|processing_event| processing_event.component_instance_uuid == uuid}

  my_events.each do |processing_event|
    connection_signature_string = processing_event.context.to_s
    if connections[connection_signature_string]
      connections[connection_signature_string].send_http_response message
    else
      conn = closed_connections.read(connection_signature_string)
      if conn
        RFlow.logger.info "#{name}: Could not send HTTP response to #{conn.client_details}: connection is already closed"
      else
        RFlow.logger.info "#{name}: Could not send HTTP response to <client details expired>: connection is already closed"
      end
    end
  end
end

#run!void

This method returns an undefined value.

RFlow-called method at startup.



57
58
59
60
61
62
63
# File 'lib/rflow/components/http/server.rb', line 57

def run!
  @server_signature = EM.start_server(@listen, @port, Connection) do |conn|
    conn.server = self
    self.connections[conn.signature.to_s] = conn
    RFlow.logger.debug { "#{name}: Connection from #{conn.client_details} to #{conn.server_details}" }
  end
end