Module: Puppet::Network::HTTP::Handler

Includes:
Issues
Defined in:
lib/puppet/network/http/handler.rb

Constant Summary collapse

DISALLOWED_KEYS =

These shouldn’t be allowed to be set by clients in the query string, for security reasons.

%w[node ip]

Constants included from Issues

Issues::ENVIRONMENT_NOT_FOUND, Issues::FAILED_AUTHORIZATION, Issues::HANDLER_NOT_FOUND, Issues::MISSING_HEADER_FIELD, Issues::NO_INDIRECTION_REMOTE_REQUESTS, Issues::RESOURCE_NOT_FOUND, Issues::RUNTIME_ERROR, Issues::UNSUPPORTED_FORMAT, Issues::UNSUPPORTED_MEDIA_TYPE, Issues::UNSUPPORTED_METHOD

Instance Method Summary collapse

Instance Method Details

#find_route_or_raise(request) ⇒ Object



108
109
110
111
112
113
114
# File 'lib/puppet/network/http/handler.rb', line 108

def find_route_or_raise(request)
  route = @routes.find { |r| r.matches?(request) }
  route || raise(Puppet::Network::HTTP::Error::HTTPNotFoundError.new(
                   _("No route for %{request} %{path}") % { request: request.method, path: request.path },
                   HANDLER_NOT_FOUND
                 ))
end

#format_to_mime(format) ⇒ Object

Deprecated.

The mime type is always passed to the ‘set_content_type` method, so it is no longer necessary to retrieve the Format’s mime type.



44
45
46
# File 'lib/puppet/network/http/handler.rb', line 44

def format_to_mime(format)
  format.is_a?(Puppet::Network::Format) ? format.mime : format
end

#headers(request) ⇒ Object

Retrieve all headers from the http request, as a hash with the header names (lower-cased) as the keys

Raises:

  • (NotImplementedError)


36
37
38
# File 'lib/puppet/network/http/handler.rb', line 36

def headers(request)
  raise NotImplementedError
end

#make_generic_request(request) ⇒ Object

Create a generic puppet request from the implementation-specific request created by the web server



50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/puppet/network/http/handler.rb', line 50

def make_generic_request(request)
  request_path = path(request)

  Puppet::Network::HTTP::Request.new(
    headers(request),
    params(request),
    http_method(request),
    request_path, # path
    request_path, # routing_path
    client_cert(request),
    body(request)
  )
end

#process(external_request, response) ⇒ Object

handle an HTTP request



78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/puppet/network/http/handler.rb', line 78

def process(external_request, response)
  # The response_wrapper stores the response and modifies it as a side effect.
  # The caller will use the original response
  response_wrapper = Puppet::Network::HTTP::Response.new(self, response)
  request = make_generic_request(external_request)

  set_puppet_version_header(response)

  respond_to_errors(response_wrapper) do
    with_request_profiling(request) do
      find_route_or_raise(request).process(request, response_wrapper)
    end
  end
end

#register(routes) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/puppet/network/http/handler.rb', line 18

def register(routes)
  # There's got to be a simpler way to do this, right?
  dupes = {}
  routes.each { |r| dupes[r.path_matcher] = (dupes[r.path_matcher] || 0) + 1 }
  dupes = dupes.filter_map { |pm, count| pm if count > 1 }
  if dupes.count > 0
    raise ArgumentError, _("Given multiple routes with identical path regexes: %{regexes}") % { regexes: dupes.map(&:inspect).join(', ') }
  end

  @routes = routes
  Puppet.debug("Routes Registered:")
  @routes.each do |route|
    Puppet.debug(route.inspect)
  end
end

#resolve_node(result) ⇒ Object

resolve node name from peer’s ip address this is used when the request is unauthenticated



132
133
134
135
136
137
138
139
# File 'lib/puppet/network/http/handler.rb', line 132

def resolve_node(result)
  begin
    return Resolv.getname(result[:ip])
  rescue => detail
    Puppet.err _("Could not resolve %{ip}: %{detail}") % { ip: result[:ip], detail: detail }
  end
  result[:ip]
end

#respond_to_errors(response) ⇒ Object



93
94
95
96
97
98
99
100
101
102
# File 'lib/puppet/network/http/handler.rb', line 93

def respond_to_errors(response)
  yield
rescue Puppet::Network::HTTP::Error::HTTPError => e
  Puppet.info(e.message)
  respond_with_http_error(response, e)
rescue StandardError => e
  http_e = Puppet::Network::HTTP::Error::HTTPServerError.new(e)
  Puppet.err([http_e.message, *e.backtrace].join("\n"))
  respond_with_http_error(response, http_e)
end

#respond_with_http_error(response, exception) ⇒ Object



104
105
106
# File 'lib/puppet/network/http/handler.rb', line 104

def respond_with_http_error(response, exception)
  response.respond_with(exception.status, "application/json", exception.to_json)
end

#set_content_type(response, format) ⇒ Object

Set the specified format as the content type of the response.

Raises:

  • (NotImplementedError)


126
127
128
# File 'lib/puppet/network/http/handler.rb', line 126

def set_content_type(response, format)
  raise NotImplementedError
end

#set_puppet_version_header(response) ⇒ Object



116
117
118
# File 'lib/puppet/network/http/handler.rb', line 116

def set_puppet_version_header(response)
  response[Puppet::Network::HTTP::HEADER_PUPPET_VERSION] = Puppet.version
end

#set_response(response, body, status = 200) ⇒ Object

Set the response up, with the body and status.

Raises:

  • (NotImplementedError)


121
122
123
# File 'lib/puppet/network/http/handler.rb', line 121

def set_response(response, body, status = 200)
  raise NotImplementedError
end

#with_request_profiling(request) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/puppet/network/http/handler.rb', line 64

def with_request_profiling(request)
  profiler = configure_profiler(request.headers, request.params)

  Puppet::Util::Profiler.profile(
    _("Processed request %{request_method} %{request_path}") % { request_method: request.method, request_path: request.path },
    [:http, request.method, request.path]
  ) do
    yield
  end
ensure
  remove_profiler(profiler) if profiler
end