Class: Puppet::Network::HTTP::RackREST
- 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
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
-
#body(request) ⇒ Object
return the request body.
-
#cleanup(request) ⇒ Object
Passenger freaks out if we finish handling the request without reading any part of the body, so make sure we have.
- #client_cert(request) ⇒ Object
- #convert_singular_arrays_to_value(hash) ⇒ Object
- #extract_client_info(request) ⇒ Object
-
#headers(request) ⇒ Object
Retrieve all headers from the http request, as a map.
-
#http_method(request) ⇒ Object
Return which HTTP verb was used in this request.
-
#initialize(args = {}) ⇒ RackREST
constructor
A new instance of RackREST.
-
#params(request) ⇒ Object
Return the query params for this request.
-
#path(request) ⇒ Object
what path was requested? (this is, without any query parameters).
- #set_content_type(response, format) ⇒ Object
-
#set_response(response, result, status = 200) ⇒ Object
produce the body of the response.
Methods included from Handler
#format_to_mime, #process, #register, #resolve_node
Constructor Details
#initialize(args = {}) ⇒ RackREST
Returns a new instance of RackREST.
30 31 32 33 34 35 |
# File 'lib/puppet/network/http/rack/rest.rb', line 30 def initialize(args={}) super() register([Puppet::Network::HTTP::API.master_routes, Puppet::Network::HTTP::API.ca_routes, Puppet::Network::HTTP::API.not_found_upgrade]) end |
Instance Method Details
#body(request) ⇒ Object
return the request body
96 97 98 |
# File 'lib/puppet/network/http/rack/rest.rb', line 96 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.
129 130 131 132 |
# File 'lib/puppet/network/http/rack/rest.rb', line 129 def cleanup(request) request.body.read(1) nil end |
#client_cert(request) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/puppet/network/http/rack/rest.rb', line 100 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? # When running with unicorn, the SSL_CLIENT_CERT variable is not available # in the environment, therefore we have to pass a header: 'X-SSL-Client-Cert' cert = request.env['HTTP_X_SSL_CLIENT_CERT'] if cert.nil? || cert.empty? nil else # in contrast to the environment variable, the client cert is passed in # as single string, therefore restore the certificate to a valid pem # encoded certificate cert.gsub!(/ /, "\n") cert.gsub!(/BEGIN\nCERT/, "BEGIN CERT") cert.gsub!(/END\nCERT/, "END CERT") cert = Puppet::SSL::Certificate.from_instance(OpenSSL::X509::Certificate.new(cert)) cert end else Puppet::SSL::Certificate.from_instance(OpenSSL::X509::Certificate.new(cert)) end end |
#convert_singular_arrays_to_value(hash) ⇒ Object
155 156 157 158 159 160 161 |
# File 'lib/puppet/network/http/rack/rest.rb', line 155 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
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/puppet/network/http/rack/rest.rb', line 134 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 59 60 |
# File 'lib/puppet/network/http/rack/rest.rb', line 53 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.
63 64 65 |
# File 'lib/puppet/network/http/rack/rest.rb', line 63 def http_method(request) request.request_method end |
#params(request) ⇒ Object
Return the query params for this request.
68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/puppet/network/http/rack/rest.rb', line 68 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)
82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/puppet/network/http/rack/rest.rb', line 82 def path(request) # The value that Passenger provides for 'path' is escaped # (URL percent-encoded), see # https://github.com/phusion/passenger/blob/release-5.0.26/src/apache2_module/Hooks.cpp#L885 # for the implementation as hooked up to an Apache web server. Code # in the indirector / HTTP layer which consumes this path, however, assumes # that it has already been unescaped, so it is unescaped here. if request.path # don't use CGI.unescape which mangles space handling URI.unescape(request.path.encode(Encoding::UTF_8)) end 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 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 |