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)



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

def http_method
  @http_method
end

#http_pathString (readonly)



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



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

def connect
  start_listener!
end

#message_queueQueue



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

def message_queue
  message_queues[queue_key]
end

#message_queuesQueue



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

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

#queue_keyString



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

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

#receive(*_) ⇒ Object



111
112
113
114
115
116
117
118
# File 'lib/carnivore-http/http_paths.rb', line 111

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

#setup(*_) ⇒ Object

Setup message queue for source



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

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



72
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
# File 'lib/carnivore-http/http_paths.rb', line 72

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 => 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
# File 'lib/carnivore-http/http_paths.rb', line 23

def terminate
  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