Class: Puppet::Network::HTTP::RackREST

Inherits:
RackHttpHandler show all
Includes:
Handler
Defined in:
lib/puppet/network/http/rack/rest.rb

Defined Under Namespace

Classes: RackFile

Constant Summary collapse

HEADER_ACCEPT =
'HTTP_ACCEPT'.freeze
ContentType =
'Content-Type'.freeze
CHUNK_SIZE =
8192

Constants included from Handler

Handler::DISALLOWED_KEYS

Constants included from API::V1

API::V1::METHOD_MAP

Instance Attribute Summary

Attributes included from Handler

#handler, #server

Instance Method Summary collapse

Methods included from Handler

#do_destroy, #do_exception, #do_find, #do_head, #do_save, #do_search, #format_to_mime, #initialize_for_puppet, #process, #request_format, #resolve_node

Methods included from Authentication

#warn_if_near_expiration

Methods included from Authorization

#authconfig, #check_authorization

Methods included from API::V1

#indirection2uri, #indirection_method, #plurality, #pluralize, #request_to_uri_and_body, #uri2indirection

Methods inherited from RackHttpHandler

#process

Constructor Details

#initialize(args = {}) ⇒ RackREST

Returns a new instance of RackREST.



32
33
34
35
# File 'lib/puppet/network/http/rack/rest.rb', line 32

def initialize(args={})
  super()
  initialize_for_puppet(args)
end

Instance Method Details

#accept_header(request) ⇒ Object

Retrieve the accept header from the http request.



61
62
63
# File 'lib/puppet/network/http/rack/rest.rb', line 61

def accept_header(request)
  request.env[HEADER_ACCEPT]
end

#body(request) ⇒ Object

return the request body



95
96
97
# File 'lib/puppet/network/http/rack/rest.rb', line 95

def body(request)
  request.body.read
end

#cleanup(request) ⇒ Object

Passenger freaks out if we finish handling the request without reading any part of the body, so make sure we have.



111
112
113
114
# File 'lib/puppet/network/http/rack/rest.rb', line 111

def cleanup(request)
  request.body.read(1)
  nil
end

#client_cert(request) ⇒ Object



99
100
101
102
103
104
105
106
107
# File 'lib/puppet/network/http/rack/rest.rb', line 99

def client_cert(request)
  # This environment variable is set by mod_ssl, note that it
  # requires the `+ExportCertData` option in the `SSLOptions` directive
  cert = request.env['SSL_CLIENT_CERT']
  # NOTE: The SSL_CLIENT_CERT environment variable will be the empty string
  # when Puppet agent nodes have not yet obtained a signed certificate.
  return nil if cert.nil? or cert.empty?
  OpenSSL::X509::Certificate.new(cert)
end

#content_type_header(request) ⇒ Object

Retrieve the accept header from the http request.



66
67
68
# File 'lib/puppet/network/http/rack/rest.rb', line 66

def content_type_header(request)
  request.content_type
end

#convert_singular_arrays_to_value(hash) ⇒ Object



137
138
139
140
141
142
143
# File 'lib/puppet/network/http/rack/rest.rb', line 137

def convert_singular_arrays_to_value(hash)
  hash.each do |key, value|
    if value.size == 1
      hash[key] = value.first
    end
  end
end

#extract_client_info(request) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/puppet/network/http/rack/rest.rb', line 116

def extract_client_info(request)
  result = {}
  result[:ip] = request.ip

  # if we find SSL info in the headers, use them to get a hostname from the CN.
  # try this with :ssl_client_header, which defaults should work for
  # Apache with StdEnvVars.
  subj_str = request.env[Puppet[:ssl_client_header]]
  subject = Puppet::Util::SSL.subject_from_dn(subj_str || "")

  if cn = Puppet::Util::SSL.cn_from_subject(subject)
    result[:node] = cn
    result[:authenticated] = (request.env[Puppet[:ssl_client_verify_header]] == 'SUCCESS')
  else
    result[:node] = resolve_node(result)
    result[:authenticated] = false
  end

  result
end

#headers(request) ⇒ Object

Retrieve all headers from the http request, as a map.



53
54
55
56
57
58
# File 'lib/puppet/network/http/rack/rest.rb', line 53

def headers(request)
  request.env.select {|k,v| k.start_with? 'HTTP_'}.inject({}) do |m, (k,v)|
    m[k.sub(/^HTTP_/, '').gsub('_','-').downcase] = v
    m
  end
end

#http_method(request) ⇒ Object

Return which HTTP verb was used in this request.



71
72
73
# File 'lib/puppet/network/http/rack/rest.rb', line 71

def http_method(request)
  request.request_method
end

#params(request) ⇒ Object

Return the query params for this request.



76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/puppet/network/http/rack/rest.rb', line 76

def params(request)
  if request.post?
    params = request.params
  else
    # rack doesn't support multi-valued query parameters,
    # e.g. ignore, so parse them ourselves
    params = CGI.parse(request.query_string)
    convert_singular_arrays_to_value(params)
  end
  result = decode_params(params)
  result.merge(extract_client_info(request))
end

#path(request) ⇒ Object

what path was requested? (this is, without any query parameters)



90
91
92
# File 'lib/puppet/network/http/rack/rest.rb', line 90

def path(request)
  request.path
end

#set_content_type(response, format) ⇒ Object



37
38
39
# File 'lib/puppet/network/http/rack/rest.rb', line 37

def set_content_type(response, format)
  response[ContentType] = format_to_mime(format)
end

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

produce the body of the response



42
43
44
45
46
47
48
49
50
# File 'lib/puppet/network/http/rack/rest.rb', line 42

def set_response(response, result, status = 200)
  response.status = status
  unless result.is_a?(File)
    response.write result
  else
    response["Content-Length"] = result.stat.size.to_s
    response.body = RackFile.new(result)
  end
end