Class: Carnivore::Source::Http

Inherits:
Carnivore::Source show all
Includes:
Http::Utils::Params
Defined in:
lib/carnivore-http/http.rb

Overview

Carnivore HTTP source

Direct Known Subclasses

HttpEndpoints

Constant Summary collapse

BODY_TO_FILE_SIZE =

Size limit for inline body

1024 * 10

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Http::Utils::Params

#format_query_args, #format_query_type, included, #parse_query_string

Instance Attribute Details

#argsHash (readonly)

Returns source arguments.

Returns:

  • (Hash)

    source arguments



15
16
17
# File 'lib/carnivore-http/http.rb', line 15

def args
  @args
end

Instance Method Details

#build_message(con, req) ⇒ Hash

Note:

if body size is greater than BODY_TO_FILE_SIZE the body will be a temp file instead of a string

Build message hash from request

Parameters:

  • con (Reel::Connection)
  • req (Reel::Request)

Returns:

  • (Hash)


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

def build_message(con, req)
  msg = Smash.new(
    :request => req,
    :headers => req.headers,
    :connection => con,
    :query => parse_query_string(req.query_string)
  )
  if(req.headers['Content-Type'] == 'application/json')
    msg[:query].merge(
      parse_query_string(
        req.body.to_s
      )
    )
    msg[:body] = req.body.to_s
  elsif(req.headers['Content-Length'].to_i > BODY_TO_FILE_SIZE)
    msg[:body] = Tempfile.new('carnivore-http')
    while((chunk = req.body.readpartial(2048)))
      msg[:body] << chunk
    end
    msg[:body].rewind
  else
    msg[:body] = req.body.to_s
  end
  format(msg)
end

#confirm(message, args = {}) ⇒ Object

Confirm processing of message

Parameters:

  • message (Carnivore::Message)
  • args (Hash) (defaults to: {})

Options Hash (args):

  • :code (Symbol)

    return code



74
75
76
77
78
79
# File 'lib/carnivore-http/http.rb', line 74

def confirm(message, args={})
  code = args.delete(:code) || :ok
  args[:response_body] = 'Thanks' if code == :ok && args.empty?
  debug "Confirming #{message} with: Code: #{code.inspect} Args: #{args.inspect}"
  message[:message][:request].respond(code, args[:response_body] || args)
end

#default_args(args = {}) ⇒ Hash

Default configuration arguments. If hash is provided, it will be merged into the default arguments.

Parameters:

  • args (Hash) (defaults to: {})

Returns:

  • (Hash)


29
30
31
32
33
34
35
# File 'lib/carnivore-http/http.rb', line 29

def default_args(args={})
  Smash.new(
    :bind => '0.0.0.0',
    :port => '3000',
    :auto_respond => true
  ).merge(args)
end

#process(*process_args) ⇒ Object

Process requests



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/carnivore-http/http.rb', line 82

def process(*process_args)
  srv = Reel::Server::HTTP.supervise(args[:bind], args[:port]) do |con|
    con.each_request do |req|
      begin
        msg = build_message(con, req)
        callbacks.each do |name|
          c_name = callback_name(name)
          debug "Dispatching #{msg} to callback<#{name} (#{c_name})>"
          callback_supervisor[c_name].call(msg)
        end
        req.respond(:ok, 'So long, and thanks for all the fish!') if args[:auto_respond]
      rescue => e
        req.respond(:bad_request, "Failed to process request -> #{e}")
      end
    end
  end
end

#setup(args = {}) ⇒ Object

Setup the source



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

def setup(args={})
  @args = default_args(args)
end

#transmit(message, *extra) ⇒ Object

Tranmit message. The transmission can be a response back to an open connection, or a request to a remote source (remote carnivore-http source generally)

Parameters:

  • message (Object)

    message to transmit

  • extras (Object)

    argument list



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/carnivore-http/http.rb', line 43

def transmit(message, *extra)
  options = extra.detect{|x| x.is_a?(Hash)} || {}
  orig = extra.detect{|x| x.is_a?(Carnivore::Message)}
  con = options[:connection]
  if(orig && con.nil?)
    con = orig[:message][:connection]
  end
  if(con) # response
    payload = message.is_a?(String) ? message : MultiJson.dump(message)
    # TODO: add `options` options for marshaling: json/xml/etc
    debug "Transmit response type with payload: #{payload}"
    con.respond(options[:code] || :ok, payload)
  else # request
    url = File.join("http://#{args[:bind]}:#{args[:port]}", options[:path].to_s)
    method = (options[:method] || :post).to_sym
    if(options[:headers])
      base = HTTP.with_headers(options[:headers])
    else
      base = HTTP
    end
    payload = message.is_a?(String) ? message : MultiJson.dump(message)
    debug "Transmit request type with payload: #{payload}"
    base.send(method, url, :body => payload)
  end
end