Class: OpenC3::HttpClientInterface

Inherits:
Interface show all
Defined in:
lib/openc3/interfaces/http_client_interface.rb

Constant Summary

Constants included from Api

Api::DELAY_METRICS, Api::DURATION_METRICS, Api::SUBSCRIPTION_DELIMITER, Api::SUM_METRICS

Constants included from ApiShared

ApiShared::DEFAULT_TLM_POLLING_RATE

Constants included from Extract

Extract::SCANNING_REGULAR_EXPRESSION

Instance Attribute Summary

Attributes inherited from Interface

#auto_reconnect, #bytes_read, #bytes_written, #cmd_routers, #cmd_target_names, #config_params, #connect_on_startup, #disable_disconnect, #interfaces, #name, #num_clients, #options, #packet_log_writer_pairs, #protocol_info, #read_count, #read_protocols, #read_queue_size, #read_raw_data, #read_raw_data_time, #reconnect_delay, #routers, #scheduler, #secrets, #state, #stored_packet_log_writer_pairs, #stream_log_pair, #target_names, #tlm_target_names, #write_count, #write_protocols, #write_queue_size, #written_raw_data, #written_raw_data_time

Instance Method Summary collapse

Methods inherited from Interface

#_write, #add_protocol, #as_json, #copy_to, #interface_cmd, #protocol_cmd, #read, #read_allowed?, #read_interface_base, #set_option, #start_raw_logging, #stop_raw_logging, #write, #write_allowed?, #write_interface_base, #write_raw, #write_raw_allowed?

Methods included from Api

#_build_cmd_output_string, #_cmd_implementation, #_get_item, #_limits_group, #_set_tlm_process_args, #_tlm_process_args, #_validate_tlm_type, #build_command, #cmd, #cmd_no_checks, #cmd_no_hazardous_check, #cmd_no_range_check, #cmd_raw, #cmd_raw_no_checks, #cmd_raw_no_hazardous_check, #cmd_raw_no_range_check, #config_tool_names, #connect_interface, #connect_router, #delete_config, #disable_limits, #disable_limits_group, #disconnect_interface, #disconnect_router, #enable_limits, #enable_limits_group, #get_all_command_names, #get_all_commands, #get_all_interface_info, #get_all_router_info, #get_all_settings, #get_all_target_info, #get_all_telemetry, #get_all_telemetry_names, #get_cmd_buffer, #get_cmd_cnt, #get_cmd_cnts, #get_cmd_hazardous, #get_cmd_time, #get_cmd_value, #get_command, #get_interface, #get_interface_names, #get_item, #get_limits, #get_limits_events, #get_limits_groups, #get_limits_set, #get_limits_sets, #get_metrics, #get_out_of_limits, #get_overall_limits_state, #get_overrides, #get_packet_derived_items, #get_packets, #get_parameter, #get_router, #get_router_names, #get_setting, #get_settings, #get_target, #get_target_interfaces, #get_target_names, #get_telemetry, #get_tlm_buffer, #get_tlm_cnt, #get_tlm_cnts, #get_tlm_packet, #get_tlm_values, #inject_tlm, #interface_cmd, #interface_protocol_cmd, #limits_enabled?, #list_configs, #list_settings, #load_config, #map_target_to_interface, #normalize_tlm, #offline_access_needed, #override_tlm, #router_cmd, #router_protocol_cmd, #save_config, #send_raw, #set_limits, #set_limits_set, #set_offline_access, #set_setting, #set_tlm, #start_raw_logging_interface, #start_raw_logging_router, #stash_all, #stash_delete, #stash_get, #stash_keys, #stash_set, #stop_raw_logging_interface, #stop_raw_logging_router, #subscribe_packets, #tlm, #tlm_formatted, #tlm_raw, #tlm_variable, #tlm_with_units

Constructor Details

#initialize(hostname, port = 80, protocol = 'http', write_timeout = 5, read_timeout = nil, connect_timeout = 5, include_request_in_response = false) ⇒ HttpClientInterface

Returns a new instance of HttpClientInterface.

Parameters:

  • hostname (String)

    HTTP/HTTPS server to connect to

  • port (Integer) (defaults to: 80)

    HTTP/HTTPS port

  • protocol (String) (defaults to: 'http')

    http or https



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/openc3/interfaces/http_client_interface.rb', line 32

def initialize(hostname, port = 80, protocol = 'http', write_timeout = 5, read_timeout = nil, connect_timeout = 5, include_request_in_response = false)
  super()
  @hostname = hostname
  @port = Integer(port)
  @protocol = protocol
  if (port == 80 and protocol == 'http') or (port == 443 and protocol == 'https')
    @url = "#{protocol}://#{hostname}"
  else
    @url = "#{protocol}://#{hostname}:#{port}"
  end
  @write_timeout = ConfigParser.handle_nil(write_timeout)
  @write_timeout = Float(@write_timeout) if @write_timeout
  @read_timeout = ConfigParser.handle_nil(read_timeout)
  @read_timeout = Float(@read_timeout) if @read_timeout
  @connect_timeout = ConfigParser.handle_nil(connect_timeout)
  @connect_timeout = Float(@connect_timeout) if @connect_timeout
  @include_request_in_response = ConfigParser.handle_true_false(include_request_in_response)

  @response_queue = Queue.new
end

Instance Method Details

#connectObject

Connects the interface to its target(s)



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/openc3/interfaces/http_client_interface.rb', line 54

def connect
  # Per https://github.com/lostisland/faraday/blob/main/lib/faraday/options/env.rb
  # :timeout       - time limit for the entire request (Integer in seconds)
  # :open_timeout  - time limit for just the connection phase (e.g. handshake) (Integer in seconds)
  # :read_timeout  - time limit for the first response byte received from the server (Integer in seconds)
  # :write_timeout - time limit for the client to send the request to the server (Integer in seconds)
  request = {}
  request['open_timeout'] = @connect_timeout if @connect_timeout
  request['read_timeout'] = @read_timeout if @read_timeout
  request['write_timeout'] = @write_timeout if @write_timeout
  @http = Faraday.new(request: request) do |f|
    f.response :follow_redirects # use Faraday::FollowRedirects::Middleware
    f.adapter :net_http # adds the adapter to the connection, defaults to `Faraday.default_adapter`
  end
  super()
end

#connected?Boolean

Returns:

  • (Boolean)


71
72
73
74
75
76
77
# File 'lib/openc3/interfaces/http_client_interface.rb', line 71

def connected?
  if @http
    return true
  else
    return false
  end
end

#convert_data_to_packet(data, extra = nil) ⇒ Packet

Called to convert the read data into a OpenC3 Packet object

Parameters:

  • data (String)

    Raw packet data

Returns:

  • (Packet)

    OpenC3 Packet with buffer filled with data



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/openc3/interfaces/http_client_interface.rb', line 154

def convert_data_to_packet(data, extra = nil)
  packet = Packet.new(nil, nil, :BIG_ENDIAN, nil, data.to_s)
  packet.accessor = HttpAccessor.new(packet)
  if extra
    # Identify the response
    request_target_name = extra['HTTP_REQUEST_TARGET_NAME']
    if request_target_name
      request_target_name = request_target_name.to_s.upcase
      response_packet_name = extra['HTTP_PACKET']
      error_packet_name = extra['HTTP_ERROR_PACKET']
      status = extra['HTTP_STATUS'].to_i
      if status >= 300 and error_packet_name
        # Handle error special case response packet
        packet.target_name = request_target_name
        packet.packet_name = error_packet_name.to_s.upcase
      else
        if response_packet_name
          packet.target_name = request_target_name
          packet.packet_name = response_packet_name.to_s.upcase
        end
      end
    end

    if not @include_request_in_response
      extra.delete("HTTP_REQUEST")
    end
    extra.delete("HTTP_REQUEST_TARGET_NAME")
    extra.delete("HTTP_REQUEST_PACKET_NAME")
    packet.extra = extra
  end

  return packet
end

#convert_packet_to_data(packet) ⇒ Object

Called to convert a packet into the data to send

Parameters:

  • packet (Packet)

    Packet to extract data from

Returns:

  • data



192
193
194
195
196
197
198
199
200
# File 'lib/openc3/interfaces/http_client_interface.rb', line 192

def convert_packet_to_data(packet)
  extra = packet.extra
  extra ||= {}
  data = packet.buffer(true) # Copy buffer so logged command isn't modified
  extra['HTTP_URI'] = URI("#{@url}#{packet.read('HTTP_PATH')}").to_s
  extra['HTTP_REQUEST_TARGET_NAME'] = packet.target_name
  extra['HTTP_REQUEST_PACKET_NAME'] = packet.packet_name
  return data, extra
end

#disconnectObject

Disconnects the interface from its target(s)



80
81
82
83
84
85
86
87
88
# File 'lib/openc3/interfaces/http_client_interface.rb', line 80

def disconnect
  @http.close if @http
  @http = nil
  while @response_queue.length > 0
    @response_queue.pop
  end
  super()
  @response_queue.push(nil)
end

#read_interfaceObject

Reads from the socket if the read_port is defined



91
92
93
94
95
96
97
98
# File 'lib/openc3/interfaces/http_client_interface.rb', line 91

def read_interface
  # Get the Faraday Response
  data, extra = @response_queue.pop
  return nil if data.nil?

  read_interface_base(data, extra)
  return data, extra
end

#write_interface(data, extra = nil) ⇒ Object

Writes to the socket

Parameters:

  • data (Hash)

    For the HTTP Interface, data is a hash with the needed request info



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/openc3/interfaces/http_client_interface.rb', line 102

def write_interface(data, extra = nil)
  extra ||= {}
  queries = extra['HTTP_QUERIES']
  queries ||= {}
  headers = extra['HTTP_HEADERS']
  headers ||= {}
  uri = extra['HTTP_URI']
  method = extra['HTTP_METHOD']

  resp = nil
  case method
  when 'get'
    resp = @http.get(uri, queries, headers)
  when 'put'
    resp = @http.put(uri) do |req|
      req.params = queries
      req.headers = headers
      req.body = data
    end
  when 'delete'
    resp = @http.delete(uri, queries, headers)
  else # 'post'
    resp = @http.post(uri) do |req|
      req.params = queries
      req.headers = headers
      req.body = data
    end
  end

  # Normalize Response into simple hash
  response_data = nil
  response_extra = {}
  if resp
    response_extra['HTTP_REQUEST'] = [data, extra]
    if resp.headers and resp.headers.length > 0
      response_extra['HTTP_HEADERS'] = resp.headers
    end
    response_extra['HTTP_STATUS'] = resp.status
    response_data = resp.body
    response_data ||= '' # Ensure an empty string if we got a response but no data
  end

  @response_queue.push([response_data, response_extra])

  write_interface_base(data, extra)
  return data, extra
end