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

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

Defined Under Namespace

Classes: RackFile

Constant Summary collapse

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

Constants included from Handler

Handler::DISALLOWED_KEYS

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_METHOD

Instance Method Summary collapse

Methods included from Handler

#format_to_mime, #process, #register, #resolve_node

Methods included from Authentication

#warn_if_near_expiration

Constructor Details

#initialize(args = {}) ⇒ RackREST

Returns a new instance of RackREST.



29
30
31
32
# File 'lib/puppet/network/http/rack/rest.rb', line 29

def initialize(args={})
  super()
  register([Puppet::Network::HTTP::API::V2.routes, Puppet::Network::HTTP::API::V1.routes])
end

Instance Method Details

#body(request) ⇒ Object

return the request body



84
85
86
# File 'lib/puppet/network/http/rack/rest.rb', line 84

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.



105
106
107
108
# File 'lib/puppet/network/http/rack/rest.rb', line 105

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

#client_cert(request) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/puppet/network/http/rack/rest.rb', line 88

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.
  if cert.nil? || cert.empty?
    nil
  else
    cert = Puppet::SSL::Certificate.from_instance(OpenSSL::X509::Certificate.new(cert))
    warn_if_near_expiration(cert)
    cert
  end
end

#convert_singular_arrays_to_value(hash) ⇒ Object



131
132
133
134
135
136
137
# File 'lib/puppet/network/http/rack/rest.rb', line 131

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



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/puppet/network/http/rack/rest.rb', line 110

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.



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

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

#http_method(request) ⇒ Object

Return which HTTP verb was used in this request.



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

def http_method(request)
  request.request_method
end

#params(request) ⇒ Object

Return the query params for this request.



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

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)



79
80
81
# File 'lib/puppet/network/http/rack/rest.rb', line 79

def path(request)
  request.path
end

#set_content_type(response, format) ⇒ Object



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

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



39
40
41
42
43
44
45
46
47
# File 'lib/puppet/network/http/rack/rest.rb', line 39

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