Class: Carnivore::Source::HttpPaths

Inherits:
HttpSource show all
Includes:
Bogo::Memoization
Defined in:
lib/carnivore-http/http_paths.rb

Overview

Carnivore HTTP paths

Constant Summary collapse

DEFAULT_RESPONSE_TIMEOUT =

Default max wait time for message response

10
DEFAULT_RESPONSE_WAIT_STEP =

Default response wait time stepping

0.1

Constants inherited from HttpSource

Carnivore::Source::HttpSource::BODY_TO_FILE_SIZE

Instance Attribute Summary collapse

Attributes inherited from HttpSource

#args, #auth_allowed_origins, #auth_htpasswd

Instance Method Summary collapse

Methods inherited from HttpSource

#allowed_credentials?, #allowed_htpasswd?, #allowed_origin?, #authorized?, #auto_process?, #build_listener, #build_message, #confirm, #default_args, #perform_transmission, #retry_delivery, #retry_directory, #retry_write_directory, #transmit, #write_for_retry

Methods included from Http::Utils::Params

#dump_query_string, #format_query_args, #format_query_type, included, #parse_query_string

Instance Attribute Details

#http_methodSymbol (readonly)

Returns http method.

Returns:

  • (Symbol)

    http method



20
21
22
# File 'lib/carnivore-http/http_paths.rb', line 20

def http_method
  @http_method
end

#http_pathString (readonly)

Returns end point path.

Returns:

  • (String)

    end point path



18
19
20
# File 'lib/carnivore-http/http_paths.rb', line 18

def http_path
  @http_path
end

Instance Method Details

#connectObject

Setup the HTTP listener source



51
52
53
# File 'lib/carnivore-http/http_paths.rb', line 51

def connect
  start_listener!
end

#message_queueQueue

Returns:

  • (Queue)


68
69
70
# File 'lib/carnivore-http/http_paths.rb', line 68

def message_queue
  message_queues[queue_key]
end

#message_queuesQueue

Returns Message queue.

Returns:

  • (Queue)

    Message queue



56
57
58
59
60
# File 'lib/carnivore-http/http_paths.rb', line 56

def message_queues
  memoize("#{args[:bind]}-#{args[:port]}-queues", :global) do
    Smash.new
  end
end

#queue_keyString

Returns:

  • (String)


63
64
65
# File 'lib/carnivore-http/http_paths.rb', line 63

def queue_key
  "#{http_path}-#{http_method}"
end

#receive(*_) ⇒ Object

Returns:

  • (Object)


114
115
116
117
118
119
120
# File 'lib/carnivore-http/http_paths.rb', line 114

def receive(*_)
  val = nil
  until(val)
    val = defer{ message_queue[:queue].pop }
  end
  val
end

#setup(*_) ⇒ Object

Setup message queue for source



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/carnivore-http/http_paths.rb', line 34

def setup(*_)
  @http_path = args.fetch(:path, '/')
  @http_method = args.fetch(:method, 'get').to_s.downcase.to_sym
  super
  if(message_queues[queue_key])
    raise ArgumentError.new "Conflicting HTTP path source provided! path: #{http_path} method: #{http_method}"
  else
    message_queues[queue_key] = Smash.new(
      :queue => Queue.new
    )
  end
  message_queues[queue_key].merge!(
    Smash.new(:config => args.to_smash)
  )
end

#start_listener!Object

Start the HTTP(S) listener



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/carnivore-http/http_paths.rb', line 73

def start_listener!
  memoize("#{args[:bind]}-#{args[:port]}", :global) do
    build_listener do |req|
      begin
        msg = build_message(req)
        # Start with static path lookup since it's the
        # cheapest, then fallback to iterative globbing
        msg_queue = nil
        unless(msg_queue = message_queues["#{req.path}-#{req.method.to_s.downcase}"])
          message_queues.each do |k,v|
            path_glob, http_method = k.split('-')
            if(req.method.to_s.downcase == http_method && File.fnmatch(path_glob, req.path))
              msg_queue = v
            end
          end
        end
        if(msg_queue)
          if(authorized?(msg))
            msg_queue[:queue] << msg
            if(msg_queue[:config][:auto_respond])
              code = msg_queue[:config].fetch(:response, :code, 'ok').to_sym
              response = msg_queue[:config].fetch(:response, :message, 'So long and thanks for all the fish!')
              req.respond(code, response)
            end
          else
            req.respond(:unauthorized, 'You are not authorized to perform requested action!')
          end
        else
          req.respond(:not_found, 'Requested path not found!')
        end
      rescue Zoidberg::DeadException
        raise
      rescue => e
        req.respond(:bad_request, "Failed to process request -> #{e}")
        puts "#{e}\n#{e.backtrace.join("\n")}"
      end
    end
  end
end

#terminateObject

Kill listener on shutdown



23
24
25
26
27
28
29
30
31
# File 'lib/carnivore-http/http_paths.rb', line 23

def terminate
  super
  listener = memoize("#{args[:bind]}-#{args[:port]}", :global){ nil }
  if(listener && listener.running)
    listener.stop(:sync)
  end
  unmemoize("#{args[:bind]}-#{args[:port]}", :global)
  unmemoize("#{args[:bind]}-#{args[:port]}-queues", :global)
end