Class: FDK::Listener

Inherits:
Object
  • Object
show all
Defined in:
lib/fdk/listener.rb

Overview

Represents the socket that Fn uses to communicate with the FDK (and thence the function) To avoid Fn trying to connect to the socket before it’s ready, the Listener creates a socket on (private_socket_path).

When the socket is ready to accept connections, the FDK links the private_socket_path to the socket_path.

Fn waits for the socket_path to be created and then connects

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url:) ⇒ Listener

Returns a new instance of Listener.



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/fdk/listener.rb', line 32

def initialize(url:)
  if url.nil? || !url.start_with?("unix:/")
    raise "Missing or invalid socket URL in FN_LISTENER."
  end

  @fn_logframe_name = ENV["FN_LOGFRAME_NAME"]
  @fn_logframe_hdr = ENV["FN_LOGFRAME_HDR"]

  @url = url
  @private_socket = UNIXServer.open(private_socket_path)
end

Instance Attribute Details

#fn_logframe_hdrObject (readonly)

Returns the value of attribute fn_logframe_hdr.



30
31
32
# File 'lib/fdk/listener.rb', line 30

def fn_logframe_hdr
  @fn_logframe_hdr
end

#fn_logframe_nameObject (readonly)

Returns the value of attribute fn_logframe_name.



30
31
32
# File 'lib/fdk/listener.rb', line 30

def fn_logframe_name
  @fn_logframe_name
end

#private_socketObject (readonly)

Returns the value of attribute private_socket.



30
31
32
# File 'lib/fdk/listener.rb', line 30

def private_socket
  @private_socket
end

#urlObject (readonly)

Returns the value of attribute url.



30
31
32
# File 'lib/fdk/listener.rb', line 30

def url
  @url
end

Instance Method Details

#handle_request(fn_block:) ⇒ Object



68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/fdk/listener.rb', line 68

def handle_request(fn_block:)
  local_socket = socket.accept
  req, resp = new_req_resp
  req.parse(local_socket)
  FDK.debug "got request #{req}"
  log_frame_header(req.header)
  fn_block.call(req, resp)
  resp["Connection"] = "close" # we're not using keep alives sadly
  resp.send_response(local_socket)
  FDK.debug "sending resp  #{resp.status}, #{resp.header}"
  local_socket.close
end


49
50
51
52
53
# File 'lib/fdk/listener.rb', line 49

def link_socket_file
  File.chmod(0o666, private_socket_path)
  FileUtils.ln_s(File.basename(private_socket_path), socket_path)
  FDK.debug "listening on #{private_socket_path}->#{socket_path}"
end

#listen(&block) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/fdk/listener.rb', line 55

def listen(&block)
  raise StandardError("No block given") unless block_given?

  begin
    loop do
      handle_request(fn_block: block)
    end
  rescue StandardError => e
    FDK.log(entry: "Error in request handling #{e}")
    FDK.log(entry: e.backtrace)
  end
end

#log_frame_header(headers) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/fdk/listener.rb', line 95

def log_frame_header(headers)
  return unless logframe_vars_exist

  k = @fn_logframe_hdr.downcase
  v = headers[k]
  return if v.nil? || v.empty?

  frm = "\n#{@fn_logframe_name}=#{v[0]}\n"
  $stderr.print frm
  $stderr.flush
  $stdout.print frm
  $stdout.flush
end

#logframe_vars_existObject



109
110
111
112
113
114
# File 'lib/fdk/listener.rb', line 109

def logframe_vars_exist
  return false if @fn_logframe_name.nil? || @fn_logframe_name.empty? ||
                  @fn_logframe_hdr.nil? || @fn_logframe_hdr.empty?

  true
end

#new_req_respObject



81
82
83
84
85
# File 'lib/fdk/listener.rb', line 81

def new_req_resp
  req = WEBrick::HTTPRequest.new(WEBrick::Config::HTTP)
  resp = WEBrick::HTTPResponse.new(WEBrick::Config::HTTP)
  [req, resp]
end

#private_socket_pathObject



91
92
93
# File 'lib/fdk/listener.rb', line 91

def private_socket_path
  "#{socket_path}.private"
end

#socketObject



44
45
46
47
# File 'lib/fdk/listener.rb', line 44

def socket
  link_socket_file unless @socket
  @socket ||= private_socket
end

#socket_pathObject



87
88
89
# File 'lib/fdk/listener.rb', line 87

def socket_path
  @socket_path ||= url[5..url.length]
end